services.py 10.3 KB
Newer Older
1 2
from collections import OrderedDict

3
from django.utils import timezone
4
from django.utils.datetime_safe import date
5 6 7 8
from django.utils.translation import ugettext_lazy as _, get_language

from events import emails
from events.exceptions import RegistrationError
9
from events.models import Registration, RegistrationInformationField, Event
10
from payments.models import Payment
11
from utils.snippets import datetime_to_lectureyear
12 13


14
def is_user_registered(member, event):
15 16
    """
    Returns if the user is registered for the specified event
17

18 19 20 21
    :param member: the user
    :param event: the event
    :return: None if registration is not required or no member else True/False
    """
22
    if not event.registration_required or not member.is_authenticated:
23 24 25
        return None

    return event.registrations.filter(
26
        member=member,
27 28 29
        date_cancelled=None).count() > 0


30
def event_permissions(member, event):
31 32
    """
    Returns a dictionary with the available event permissions of the user
33

34 35 36 37
    :param member: the user
    :param event: the event
    :return: the permission dictionary
    """
38 39 40 41 42
    perms = {
        "create_registration": False,
        "cancel_registration": False,
        "update_registration": False,
    }
43
    if member and member.is_authenticated:
44 45 46 47
        registration = None
        try:
            registration = Registration.objects.get(
                event=event,
48
                member=member
49 50 51 52 53 54
            )
        except Registration.DoesNotExist:
            pass

        perms["create_registration"] = (
            (registration is None or registration.date_cancelled is not None)
55 56
            and event.registration_allowed and
            member.can_attend_events)
57 58 59 60 61 62
        perms["cancel_registration"] = (
            registration is not None and
            registration.date_cancelled is None and
            event.cancellation_allowed)
        perms["update_registration"] = (
            registration is not None and
63 64 65 66
            registration.date_cancelled is None and
            event.has_fields() and
            event.registration_allowed and
            member.can_attend_events)
67 68 69 70

    return perms


71
def is_organiser(member, event):
72 73 74
    if member and member.is_authenticated:
        if member.is_superuser or member.has_perm("events.override_organiser"):
            return True
75

76
        if event:
77
            return member.get_member_groups().filter(
78
                    pk=event.organiser.pk).count() != 0
79 80 81 82

    return False


83
def create_registration(member, event):
84 85
    """
    Creates a new user registration for an event
86

87 88 89 90
    :param member: the user
    :param event: the event
    :return: returns the registration if successful
    """
91
    if event_permissions(member, event)["create_registration"]:
92 93 94 95
        registration = None
        try:
            registration = Registration.objects.get(
                event=event,
96
                member=member
97 98 99 100 101 102 103
            )
        except Registration.DoesNotExist:
            pass

        if registration is None:
            return Registration.objects.create(
                event=event,
104
                member=member
105 106 107 108 109 110 111 112 113 114 115 116
            )
        elif registration.date_cancelled is not None:
            if registration.is_late_cancellation():
                raise RegistrationError(_("You cannot re-register anymore "
                                          "since you've cancelled after the "
                                          "deadline."))
            else:
                registration.date = timezone.now()
                registration.date_cancelled = None
                registration.save()

        return registration
117
    elif event_permissions(member, event)["cancel_registration"]:
118 119 120 121 122
        raise RegistrationError(_("You were already registered."))
    else:
        raise RegistrationError(_("You may not register."))


123
def cancel_registration(member, event):
124 125
    """
    Cancel a user registration for an event
126

127 128 129
    :param member: the user
    :param event: the event
    """
130 131 132 133
    registration = None
    try:
        registration = Registration.objects.get(
            event=event,
134
            member=member
135 136 137 138
        )
    except Registration.DoesNotExist:
        pass

139 140
    if (event_permissions(member, event)["cancel_registration"] and
            registration):
141
        if registration.queue_position == 0:
142
            emails.notify_first_waiting(event)
143

144 145 146 147
            if (event.send_cancel_email and
                    event.after_cancel_deadline):
                emails.notify_organiser(event, registration)

148 149 150 151 152 153 154 155 156 157
        # 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.
        registration.date_cancelled = timezone.now()
        registration.save()
    else:
        raise RegistrationError(_("You are not registered for this event."))


158 159
def update_registration(member=None, event=None,
                        registration=None, field_values=None):
160 161
    """
    Updates a user registration of an event
162

163
    :param request: http request
164 165
    :param member: the user
    :param event: the event
166
    :param registration: the registration
167 168
    :param field_values: values for the information fields
    """
169
    if not registration:
170 171 172 173 174 175 176 177 178 179 180
        try:
            registration = Registration.objects.get(
                event=event,
                member=member
            )
        except Registration.DoesNotExist as error:
            raise RegistrationError(
                _("You are not registered for this event.")) from error
    else:
        member = registration.member
        event = registration.event
181

182 183
    if (not event_permissions(member, event)["update_registration"] or
            not field_values):
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
        return

    for field_id, field_value in field_values:
        field = RegistrationInformationField.objects.get(
            id=field_id.replace("info_field_", ""))

        if (field.type == RegistrationInformationField.INTEGER_FIELD
                and field_value is None):
            field_value = 0
        elif (field.type == RegistrationInformationField.BOOLEAN_FIELD
                and field_value is None):
            field_value = False
        elif (field.type == RegistrationInformationField.TEXT_FIELD
              and field_value is None):
            field_value = ''

        field.set_value_for(registration, field_value)


203
def registration_fields(request, member=None, event=None, registration=None):
204 205
    """
    Returns information about the registration fields of a registration
206

207 208 209
    :param member: the user (optional if registration provided)
    :param event: the event (optional if registration provided)
    :param registration: the registration (optional if member & event provided)
210 211
    :return: the fields
    """
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

    if registration is None:
        try:
            registration = Registration.objects.get(
                event=event,
                member=member
            )
        except Registration.DoesNotExist as error:
            raise RegistrationError(
                _("You are not registered for this event.")) from error
        except Registration.MultipleObjectsReturned as error:
            raise RegistrationError(
                _("Unable to find the right registration.")) from error
    else:
        member = registration.member
        event = registration.event
228

229 230 231
    perms = (event_permissions(member, event)["update_registration"] or
             is_organiser(request.member, event))
    if perms and registration:
232
        information_fields = registration.information_fields
233
        fields = OrderedDict()
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

        for information_field in information_fields:
            field = information_field["field"]

            fields["info_field_{}".format(field.id)] = {
                "type": field.type,
                "label": getattr(field, "{}_{}".format(
                    "name",  get_language())),
                "description": getattr(field, "{}_{}".format(
                    "description", get_language())),
                "value": information_field["value"],
                "required": field.required
            }

        return fields
    else:
250 251
        raise RegistrationError(
            _("You are not allowed to update this registration."))
252 253 254 255 256 257 258 259


def update_registration_by_organiser(registration, member, data):
    if not is_organiser(member, registration.event):
        raise RegistrationError(
            _("You are not allowed to update this registration."))

    if 'payment' in data:
260 261 262 263 264 265 266 267 268 269
        if (data['payment']['type'] == Payment.NONE
                and registration.payment is not None):
            p = registration.payment
            registration.payment = None
            registration.save()
            p.delete()
        elif (data['payment']['type'] != Payment.NONE
              and registration.payment is not None):
            registration.payment.type = data['payment']['type']
            registration.payment.save()
270
        elif (data['payment']['type'] != Payment.NONE
271
              and registration.payment is None):
272 273 274 275 276 277 278

            note = f'Event registration {registration.event.title_en}. '
            if registration.name:
                note += f'Paid by {registration.name}. '
            note += (f'{registration.event.start}. '
                     f'Registration date: {registration.date}.')

279 280 281
            registration.payment = Payment.objects.create(
                amount=registration.event.price,
                paid_by=registration.member,
282
                notes=note,
283 284 285
                processed_by=member,
                type=data['payment']['type']
            )
286 287 288 289 290

    if 'present' in data:
        registration.present = data['present']

    registration.save()
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311


def generate_category_statistics():
    """
    Generate statistics about events, number of events per category
    :return: Dict with key, value resp. being category, event count.
    """
    year = datetime_to_lectureyear(timezone.now())

    data = {}
    for i in range(5):
        year_start = date(year=year - i, month=9, day=1)
        year_end = date(year=year - i + 1, month=9, day=1)
        data[str(year - i)] = {
            str(display): Event.objects.filter(category=key,
                                               start__gte=year_start,
                                               end__lte=year_end).count()
            for key, display in Event.EVENT_CATEGORIES
        }

    return data