Source code for events.services

from collections import OrderedDict

from django.utils import timezone
from django.utils.datetime_safe import date
from django.utils.translation import gettext_lazy as _, get_language

from events import emails
from events.exceptions import RegistrationError
from events.models import EventRegistration, RegistrationInformationField, Event
from payments.api.fields import PaymentTypeField
from payments.models import Payment
from payments.services import create_payment, delete_payment
from utils.snippets import datetime_to_lectureyear


[docs]def is_user_registered(member, event): """ Returns if the user is registered for the specified event :param member: the user :param event: the event :return: None if registration is not required or no member else True/False """ if not event.registration_required or not member.is_authenticated: return None return event.registrations.filter(member=member, date_cancelled=None).count() > 0
[docs]def event_permissions(member, event, name=None): """ Returns a dictionary with the available event permissions of the user :param member: the user :param event: the event :param name: the name of a non member registration :return: the permission dictionary """ perms = { "create_registration": False, "cancel_registration": False, "update_registration": False, } if not member: return perms if not (member.is_authenticated or name): return perms registration = None try: registration = EventRegistration.objects.get( event=event, member=member, name=name ) except EventRegistration.DoesNotExist: pass perms["create_registration"] = ( (registration is None or registration.date_cancelled is not None) and event.registration_allowed and (name or member.can_attend_events) ) perms["cancel_registration"] = ( registration is not None and registration.date_cancelled is None and (event.cancellation_allowed or name) ) perms["update_registration"] = ( registration is not None and registration.date_cancelled is None and event.has_fields() and event.registration_allowed and (name or member.can_attend_events) ) return perms
[docs]def is_organiser(member, event): if member and member.is_authenticated: if member.is_superuser or member.has_perm("events.override_organiser"): return True if event: return member.get_member_groups().filter(pk=event.organiser.pk).count() != 0 return False
[docs]def create_registration(member, event): """ Creates a new user registration for an event :param member: the user :param event: the event :return: returns the registration if successful """ if event_permissions(member, event)["create_registration"]: registration = None try: registration = EventRegistration.objects.get(event=event, member=member) except EventRegistration.DoesNotExist: pass if registration is None: return EventRegistration.objects.create(event=event, member=member) 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 elif event_permissions(member, event)["cancel_registration"]: raise RegistrationError(_("You were already registered.")) else: raise RegistrationError(_("You may not register."))
[docs]def cancel_registration(member, event): """ Cancel a user registration for an event :param member: the user :param event: the event """ registration = None try: registration = EventRegistration.objects.get(event=event, member=member) except EventRegistration.DoesNotExist: pass if event_permissions(member, event)["cancel_registration"] and registration: if registration.payment is not None: delete_payment(registration) if registration.queue_position == 0: emails.notify_first_waiting(event) if event.send_cancel_email and event.after_cancel_deadline: emails.notify_organiser(event, registration) # 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."))
[docs]def pay_with_tpay(member, event): """ Add a Thalia Pay payment to an event registration :param member: the user :param event: the event """ try: registration = EventRegistration.objects.get(event=event, member=member) except EventRegistration.DoesNotExist: raise RegistrationError(_("You are not registered for this event.")) if registration.payment is None: registration.payment = create_payment( payable=registration, processed_by=member, pay_type=Payment.TPAY ) registration.save() else: raise RegistrationError(_("You have already paid for this event."))
[docs]def update_registration( member=None, event=None, name=None, registration=None, field_values=None ): """ Updates a user registration of an event :param request: http request :param member: the user :param event: the event :param name: the name of a registration not associated with a user :param registration: the registration :param field_values: values for the information fields """ if not registration: try: registration = EventRegistration.objects.get( event=event, member=member, name=name ) except EventRegistration.DoesNotExist as error: raise RegistrationError( _("You are not registered for this event.") ) from error else: member = registration.member event = registration.event name = registration.name if ( not event_permissions(member, event, name)["update_registration"] or not field_values ): 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)
[docs]def registration_fields(request, member=None, event=None, registration=None, name=None): """ Returns information about the registration fields of a registration :param member: the user (optional if registration provided) :param name: the name of a non member registration (optional if registration provided) :param event: the event (optional if registration provided) :param registration: the registration (optional if member & event provided) :return: the fields """ if registration is None: try: registration = EventRegistration.objects.get( event=event, member=member, name=name ) except EventRegistration.DoesNotExist as error: raise RegistrationError( _("You are not registered for this event.") ) from error except EventRegistration.MultipleObjectsReturned as error: raise RegistrationError( _("Unable to find the right registration.") ) from error else: member = registration.member event = registration.event name = registration.name perms = event_permissions(member, event, name)[ "update_registration" ] or is_organiser(request.member, event) if perms and registration: information_fields = registration.information_fields fields = OrderedDict() 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: raise RegistrationError(_("You are not allowed to update this registration."))
[docs]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: if data["payment"]["type"] == PaymentTypeField.NO_PAYMENT: if registration.payment is not None: delete_payment(registration) else: registration.payment = create_payment( payable=registration, processed_by=member, pay_type=data["payment"]["type"], ) if "present" in data: registration.present = data["present"] registration.save()
[docs]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