Skip to content
Snippets Groups Projects
views.py 37.7 KiB
Newer Older
from typing import Optional

Tom Teichler's avatar
Tom Teichler committed
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.syndication.views import Feed
from django.core.exceptions import ValidationError
from django.http import HttpRequest, HttpResponse
Julian's avatar
Julian committed
from django.shortcuts import redirect, render
from django.urls import reverse, reverse_lazy
Tom Teichler's avatar
Tom Teichler committed
from django.utils import timezone
Tom Teichler's avatar
Tom Teichler committed
from django.utils.decorators import method_decorator
from django.utils.text import slugify
from django.utils.translation import gettext as _
Tom Teichler's avatar
Tom Teichler committed
from django.views.decorators.cache import never_cache
from django.views.generic import FormView, TemplateView, View
Tom Teichler's avatar
Tom Teichler committed
from django.views.generic.detail import DetailView
Tom Teichler's avatar
Tom Teichler committed

import reversion
from django_tables2 import RequestConfig
Tom Teichler's avatar
Tom Teichler committed
from django_tables2.views import SingleTableView
from formtools.wizard.views import SessionWizardView
from reversion.views import RevisionMixin
Tom Teichler's avatar
Tom Teichler committed
from rules.contrib.views import PermissionRequiredMixin, permission_required
from templated_email import send_templated_mail

Tom Teichler's avatar
Tom Teichler committed
from aleksis.apps.postbuero.models import MailAddress
from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
Tom Teichler's avatar
Tom Teichler committed
from aleksis.core.models import Activity, Group, Person
Tom Teichler's avatar
Tom Teichler committed
from aleksis.core.util import messages
Tom Teichler's avatar
Tom Teichler committed
from aleksis.core.util.core_helpers import get_site_preferences, objectgetter_optional
Tom Teichler's avatar
Tom Teichler committed

from .filters import EventFilter, EventRegistrationFilter, VoucherFilter
Tom Teichler's avatar
Tom Teichler committed
from .forms import (
    EditEventForm,
    EditEventRegistrationForm,
    EditInfoMailingForm,
    EditTermForm,
Tom Teichler's avatar
Tom Teichler committed
    EditVoucherForm,
    GenerateListForm,
Tom Teichler's avatar
Tom Teichler committed
    PersonGroupFormPerson,
Tom Teichler's avatar
Tom Teichler committed
    RegistrationNotificationForm,
    RegistrationStatesForm,
Tom Teichler's avatar
Tom Teichler committed
)
Tom Teichler's avatar
Tom Teichler committed
from .models import (
    Event,
    EventRegistration,
    InfoMailing,
    RegistrationState,
    Terms,
    Voucher,
)
from .tables import (
Tom Teichler's avatar
Tom Teichler committed
    ChildGroupsTable,
    EventRegistrationsTable,
    InfoMailingsTable,
    ManageEventsTable,
Tom Teichler's avatar
Tom Teichler committed
    RegistrationStatesTable,
    TermsTable,
    VouchersTable,
)
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
User = get_user_model()
Tom Teichler's avatar
Tom Teichler committed
@method_decorator(never_cache, name="dispatch")
class CreateEventView(PermissionRequiredMixin, AdvancedCreateView):
    form_class = EditEventForm
    model = Event
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_events_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event/create.html"
    success_url = reverse_lazy("manage_events")
Tom Teichler's avatar
Tom Teichler committed
    success_message = _("The event has been saved.")
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
@method_decorator(never_cache, name="dispatch")
class EditEventView(PermissionRequiredMixin, RevisionMixin, AdvancedEditView):
    form_class = EditEventForm
    model = Event
    slug_field = "slug"
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_event_rule"
Tom Teichler's avatar
Tom Teichler committed
    context_object_name = "manage_events"
    template_name = "paweljong/event/edit.html"
    success_url = reverse_lazy("manage_events")
    success_message = _("The event has been saved.")
Tom Teichler's avatar
Tom Teichler committed
@permission_required("paweljong.view_events_rule")
Tom Teichler's avatar
Tom Teichler committed
def manage_events(request: HttpRequest) -> HttpResponse:
    """List view listing all registrations."""
    context = {}
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    # Get all registrations
    now = timezone.datetime.today()
    events = Event.objects.all()
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    # Get filter
    events_filter = EventFilter(request.GET, queryset=events)
    context["events_filter"] = events_filter
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    # Build table
    events_table = ManageEventsTable(events_filter.qs)
    RequestConfig(request).configure(events_table)
    context["events_table"] = events_table
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    return render(request, "paweljong/event/manage.html", context)
Tom Teichler's avatar
Tom Teichler committed
@permission_required("paweljong.view_vouchers_rule")
Tom Teichler's avatar
Tom Teichler committed
def vouchers(request):
    context = {}

    # Get all unused vouchers
    vouchers = Voucher.objects.filter(used=False, deleted=False)

    # Get filter
    vouchers_filter = VoucherFilter(request.GET, queryset=vouchers)
    context["vouchers_filter"] = vouchers_filter

    # Build table
    vouchers_table = VouchersTable(vouchers_filter.qs)
    RequestConfig(request).configure(vouchers_table)
    context["vouchers_table"] = vouchers_table

    return render(request, "paweljong/voucher/list.html", context)


Tom Teichler's avatar
Tom Teichler committed
@permission_required("paweljong.generate_lists_rule")
Tom Teichler's avatar
Tom Teichler committed
def generate_lists(request: HttpRequest) -> HttpResponse:
    context = {}

    generate_list_form = GenerateListForm()

    if request.method == "POST":
        generate_list_form = GenerateListForm(request.POST)
        if generate_list_form.is_valid():
            context["group"] = generate_list_form.cleaned_data["group"]
            template = generate_list_form.cleaned_data["template"]
            context["landscape"] = generate_list_form.cleaned_data["landscape"]

            return render(request, "paweljong/print/%s.html" % (template), context)

    context["generate_list_form"] = generate_list_form

    return render(request, "paweljong/print/manage.html", context)


Tom Teichler's avatar
Tom Teichler committed
@method_decorator(never_cache, name="dispatch")
class EventRegistrationCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for event registrations."""
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    model = EventRegistration
    form_class = EditEventRegistrationForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_registration_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event_registration/create.html"
Tom Teichler's avatar
Tom Teichler committed
    success_url = reverse_lazy("manage_events")
Tom Teichler's avatar
Tom Teichler committed
    success_message = _("The event registration has been created.")
Tom Teichler's avatar
Tom Teichler committed
@method_decorator(never_cache, name="dispatch")
class EventRegistrationEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for event registrations."""
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    model = EventRegistration
    form_class = EditEventRegistrationForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_registration_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event_registration/edit.html"
Tom Teichler's avatar
Tom Teichler committed
    success_url = reverse_lazy("manage_events")
Tom Teichler's avatar
Tom Teichler committed
    success_message = _("The event registration has been saved.")
Tom Teichler's avatar
Tom Teichler committed


@permission_required(
Tom Teichler's avatar
Tom Teichler committed
    "paweljong.change_registration_rule",
Tom Teichler's avatar
Tom Teichler committed
    fn=objectgetter_optional(EventRegistration, None, False),
)
Tom Teichler's avatar
Tom Teichler committed
def edit_registration(request: HttpRequest, pk) -> HttpResponse:
Tom Teichler's avatar
Tom Teichler committed
    context = {}

Tom Teichler's avatar
Tom Teichler committed
    registration = objectgetter_optional(EventRegistration, None, False)(request, pk)
Tom Teichler's avatar
Tom Teichler committed

    edit_event_registration_form = EditEventRegistrationForm(
        request.POST or None, instance=registration
    )

    if request.method == "POST":
        if edit_event_registration_form.is_valid():
            with reversion.create_revision():
                edit_event_registration_form.save(commit=True)

            messages.success(request, _("The registration has been saved."))

            return redirect("registration")

    context["edit_event_registration_form"] = edit_event_registration_form

    return render(request, "paweljong/event_registration/edit.html", context)


Tom Teichler's avatar
Tom Teichler committed
@permission_required("paweljong.view_voucher_rule", fn=objectgetter_optional(Voucher, None, False))
Tom Teichler's avatar
Tom Teichler committed
def print_voucher(request: HttpRequest, pk) -> HttpResponse:
Tom Teichler's avatar
Tom Teichler committed
    context = {}

Tom Teichler's avatar
Tom Teichler committed
    voucher = Voucher.objects.get(id=pk)
Tom Teichler's avatar
Tom Teichler committed
    context["voucher"] = voucher

    return render(request, "paweljong/print/voucher.html", context)


Tom Teichler's avatar
Tom Teichler committed
class EventRegistrationDetailView(PermissionRequiredMixin, DetailView):
    """Detail view for an application instance."""

    context_object_name = "registration"
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.view_registration_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event_registration/full.html"

    def get_queryset(self):
        return EventRegistration.objects.all()

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)

        invoice = self.get_object().get_invoice()
        context["invoice"] = invoice

        return context

Tom Teichler's avatar
Tom Teichler committed

class EventRegistrationDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
    """Delete view for registrations."""

    model = EventRegistration
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.delete_eventregistration_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "core/pages/delete.html"
Tom Teichler's avatar
Tom Teichler committed
    success_url = reverse_lazy("manage_events")
Tom Teichler's avatar
Tom Teichler committed
    success_message = _("The registration has been deleted.")


@method_decorator(never_cache, name="dispatch")
class VoucherCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for vouchers."""

    model = Voucher
    form_class = EditVoucherForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_voucher_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/voucher/create.html"
    success_url = reverse_lazy("vouchers")
    success_message = _("The voucher has been created.")


@method_decorator(never_cache, name="dispatch")
class VoucherEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for vouchers."""

    model = Voucher
    form_class = EditVoucherForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_voucher_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/voucher/edit.html"
    success_url = reverse_lazy("vouchers")
    success_message = _("The voucher has been saved.")


class VoucherDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
    """Delete view for vouchers."""

    model = Voucher
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.delete_voucher_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("vouchers")
    success_message = _("The voucher has been deleted.")


def is_person_anonymous(wizard):
    return wizard.request.user.is_anonymous


def set_email_needed(request, slug: Optional[str] = None):
Tom Teichler's avatar
Tom Teichler committed
    request.session["email_needed"] = True
    if slug:
        return redirect("register_event_by_slug", slug)
    else:
        return redirect("register_account")
Tom Teichler's avatar
Tom Teichler committed


def is_email_needed(wizard):
    return wizard.request.session.pop("email_needed", None)
TEMPLATES = {
Tom Teichler's avatar
Tom Teichler committed
    "email": "paweljong/event/register_wizard.html",
    "register": "paweljong/event/register_wizard.html",
    "contact_details": "paweljong/event/register_wizard.html",
    "guardians": "paweljong/event/register_wizard.html",
    "additional": "paweljong/event/register_wizard.html",
    "financial": "paweljong/event/register_wizard.html",
    "consent": "paweljong/event/register_wizard_consent.html",
}

class AccountRegisterWizardView(SessionWizardView):
    template_name = "paweljong/account_wizard.html"
    file_storage = settings.DEFAULT_FILE_STORAGE

    def get_form_kwargs(self, step):
        kwargs = super().get_form_kwargs()
        if step == "email":
            kwargs["request"] = self.request
        return kwargs

    def get_form_initial(self, step):
        initial = self.initial_dict.get(step, {})

        if step == "register":
            cleaned_data_email = self.get_cleaned_data_for_step("email")
            if cleaned_data_email:
                domain = cleaned_data_email["domain"]
                email = f"{cleaned_data_email['local_part']}@{domain.domain}"
                initial.update(
                    {
                        "email": email,
                        "email2": email,
                    }
                )

        if step == "contact_details":
            cleaned_data_register = self.get_cleaned_data_for_step("register")
            if cleaned_data_register:
                initial.update(
                    {
                        "first_name": cleaned_data_register["first_name"],
                        "last_name": cleaned_data_register["last_name"],
                        "email": cleaned_data_register["email"],
                        "date_of_birth": cleaned_data_register["date_of_birth"],
                    }
                )

        return self.initial_dict.get(step, initial)

    def done(self, form_list, **kwargs):
        context = {}
        cleaned_data_email = self.get_cleaned_data_for_step("email")
        cleaned_data_register = self.get_cleaned_data_for_step("register")

        # Create email address
        if cleaned_data_email:
            _email = MailAddress.objects.create(
                local_part=cleaned_data_email["local_part"],
                domain=cleaned_data_email["domain"],
            )

        # Create user
        if cleaned_data_register:
            user = User.objects.create(
                username=cleaned_data_register["username"],
                email=cleaned_data_register["email"],
            )
            user.set_password(cleaned_data_register["password1"])
            user.save()
        else:
            user = self.request.user

        person, created = Person.objects.get_or_create(
            user=user,
            defaults={
                "email": cleaned_data_register["email"],
                "first_name": cleaned_data_register["first_name"],
                "last_name": cleaned_data_register["last_name"],
                "date_of_birth": cleaned_data_register["date_of_birth"],
            },
        )

        context["person"] = person

        send_templated_mail(
            template_name="account_registered",
            from_email=get_site_preferences()["mail__address"],
Julian's avatar
Julian committed
            recipient_list=["root@teckids.org"],
            headers={
                "reply_to": [
                    person.email,
                ],
                "X-Zammad-Customer-Email": person.email,
            },
            context=context,
        )

        if _email:
            _email.person = person
            _email.save()

        return redirect("index")

Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
class RegisterEventWizardView(SessionWizardView):
    template_name = "paweljong/event/register_wizard.html"
    file_storage = settings.DEFAULT_FILE_STORAGE

    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

Tom Teichler's avatar
Tom Teichler committed
    def get_context_data(self, form, **kwargs):
        context = super().get_context_data(form, **kwargs)
        context["event"] = Event.objects.get(slug=self.kwargs["slug"])
Tom Teichler's avatar
Tom Teichler committed

        if self.steps.current == "email":
            context["info_title"] = _("Create e-mail address")
            context["info_text"] = _(
                "All participants need a personal e-mail address, which they check and read "
                "temselves. We offer the possibility to register an e-mail address "
                "on our secure servers, made for young users. For information about receiving "
                "mails, see: "
                "<a href='https://leopard.institute/pages/services.html'>https://leopard.institute/pages/services.html</a>."  # noqa
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "register":
            context["info_title"] = _("Event registration")
            context["info_text"] = _(
                "First, please enter some basic information about yourself, and check "
                "whether all information is correct."
            )
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "contact_details":
            context["info_title"] = _("Contact information")
            context["info_text"] = _(
                "Tell us how we can contact you. You will receive information about "
                "the event by e-mail. Please use your personal e-mail address "
                "where you will read mails yourself, not an address of your parents. "
                "We will always send all important information to your parents as well, "
                "and you will enter their e-mail address on the next page."
            )
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "guardians":
            context["info_title"] = _("Legal guardians / parents")
            context["info_text"] = _(
                "Tell us how we can reach your parents or other legal guardians. "
                "This should be the person who was present when you registered for the "
                "event (which is now). If you want to add another parent, please tell us "
                "later as a comment."
            )
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "additional":
            context["info_title"] = _("Additional registration information")
            context["info_text"] = _(
                "Please answer the following questions as precisely as you can, so "
                "we can make sure your event attendance will be organised as wel las possible."
            )
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "financial":
            context["info_title"] = _("Payment")
            context["info_text"] = _(
                "Please decide with your parents how you want to pay. In this step, "
                "you only select a payment method. The real payment will be done "
                "in a separate step, after the registration is complete."
Tom Teichler's avatar
Tom Teichler committed
        elif self.steps.current == "consent":
            context["info_title"] = _("Consent")
            context["info_text"] = _(
                "Lastly, please read the terms and conditions carefully, together "
                "with your parents. After that, you will need to confirm that you "
                "agree with everything yourself, and that your parents also agree."
            )
Tom Teichler's avatar
Tom Teichler committed

        return context

    def get_form_kwargs(self, step):
        kwargs = super().get_form_kwargs()
        if step == "email":
            kwargs["request"] = self.request
Hangzhi Yu's avatar
Hangzhi Yu committed
        if step == "additional":
            event = Event.objects.get(slug=self.kwargs["slug"])
            kwargs["event"] = event
        if step == "consent":
            event = Event.objects.get(slug=self.kwargs["slug"])
Tom Teichler's avatar
Tom Teichler committed
            kwargs["event"] = event
        return kwargs

    def get_form_initial(self, step):
        initial = self.initial_dict.get(step, {})

        if step == "register":
            cleaned_data_email = self.get_cleaned_data_for_step("email")
            if cleaned_data_email:
                domain = cleaned_data_email["domain"]
                email = f"{cleaned_data_email['local_part']}@{domain.domain}"
                initial.update(
                    {
                        "email": email,
                        "email2": email,
                    }
                )
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
        if step == "guardians":
            if hasattr(self.request.user, "person"):
                person = self.request.user.person
                if person.guardians.first():
                    initial.update(
                        {
                            "guardian_first_name": person.guardians.first().first_name,
                            "guardian_last_name": person.guardians.first().last_name,
                            "guardian_mobile_number": person.guardians.first().mobile_number,
                            "guardian_email": person.guardians.first().email,
                        }
                    )

        if step == "contact_details":
            if hasattr(self.request.user, "person"):
                person = self.request.user.person
                initial.update(
                    {
                        "first_name": person.first_name,
                        "last_name": person.last_name,
                        "mobile_number": person.mobile_number,
                        "email": person.email,
                        "street": person.street,
                        "place": person.place,
                        "housenumber": person.housenumber,
                        "sex": person.sex,
                        "date_of_birth": person.date_of_birth,
                        "postal_code": person.postal_code,
                    }
Tom Teichler's avatar
Tom Teichler committed
            else:
                cleaned_data_register = self.get_cleaned_data_for_step("register")
                if cleaned_data_register:
                    initial.update(
                        {
                            "first_name": cleaned_data_register["first_name"],
                            "last_name": cleaned_data_register["last_name"],
                            "email": cleaned_data_register["email"],
                            "date_of_birth": cleaned_data_register["date_of_birth"],
Tom Teichler's avatar
Tom Teichler committed
        if step == "financial":
            if getattr(self.request.user, "person", None):
                vouchers = Voucher.objects.filter(
                    person=self.request.user.person, event__slug=self.kwargs["slug"], used=False
                )
                if vouchers:
                    initial.update({"voucher_code": vouchers.first().code})

Tom Teichler's avatar
Tom Teichler committed
        return self.initial_dict.get(step, initial)

    def done(self, form_list, **kwargs):
        event = Event.objects.get(slug=self.kwargs["slug"])
        try:
            cleaned_data_email = self.get_cleaned_data_for_step("email")
        except KeyError: # FIXME
            cleaned_data_email = False
        cleaned_data_contact_details = self.get_cleaned_data_for_step("contact_details")
Tom Teichler's avatar
Tom Teichler committed
        cleaned_data_guardians = self.get_cleaned_data_for_step("guardians")
        try:
            cleaned_data_register = self.get_cleaned_data_for_step("register")
        except KeyError: # FIXME
            cleaned_data_register = False
Tom Teichler's avatar
Tom Teichler committed
        cleaned_data_additional = self.get_cleaned_data_for_step("additional")
        cleaned_data_financial = self.get_cleaned_data_for_step("financial")
        cleaned_data_consent = self.get_cleaned_data_for_step("consent")

Tom Teichler's avatar
Tom Teichler committed
        if cleaned_data_financial["voucher_code"]:
            if getattr(self.request.user, "person", None):
                vouchers = Voucher.objects.filter(
Julian's avatar
Julian committed
                    person=self.request.user.person,
                    event=event,
                    used=False,
                    code=cleaned_data_financial["voucher_code"],
                )
                if vouchers:
                    voucher = vouchers.first()
                else:
                    messages.error(self.request, _("You entered an invalid voucher code!"))
Tom Teichler's avatar
Tom Teichler committed
        # Create email address
        if cleaned_data_email:
            _email = MailAddress.objects.create(
                local_part=cleaned_data_email["local_part"],
                domain=cleaned_data_email["domain"],
            )

        # Create user
        if cleaned_data_register:
            user = User.objects.create(
                username=cleaned_data_register["username"],
                email=cleaned_data_register["email"],
            )
            user.set_password(cleaned_data_register["password1"])
            user.save()
Tom Teichler's avatar
Tom Teichler committed
        person, created = Person.objects.get_or_create(
            user=user,
            defaults={
                "email": cleaned_data_contact_details["email"],
                "first_name": cleaned_data_contact_details["first_name"],
                "last_name": cleaned_data_contact_details["last_name"],
Tom Teichler's avatar
Tom Teichler committed
            "mobile_number" in cleaned_data_contact_details
Tom Teichler's avatar
Tom Teichler committed
            or "sex" in cleaned_data_contact_details
            or "date_of_birth" in cleaned_data_contact_details
        ):
            person.mobile_number = cleaned_data_contact_details["mobile_number"]
            person.sex = cleaned_data_contact_details["sex"]
            person.date_of_birth = cleaned_data_contact_details["date_of_birth"]

            person.save()

        # Store postal address in database
        if (
            "postal_code" in cleaned_data_contact_details
            or "place" in cleaned_data_contact_details
            or "street" in cleaned_data_contact_details
        ):
            person.street = cleaned_data_contact_details["street"]
            person.postal_code = cleaned_data_contact_details["postal_code"]
            person.place = cleaned_data_contact_details["place"]
            person.housenumber = cleaned_data_contact_details["housenumber"]
Tom Teichler's avatar
Tom Teichler committed
            person.save()

        if (
            "guardian_first_name" in cleaned_data_guardians
            or "guardian_last_name" in cleaned_data_guardians
            or "guardian_mobile_number" in cleaned_data_guardians
            or "guardian_email" in cleaned_data_guardians
        ):
Tom Teichler's avatar
Tom Teichler committed
            guardian, created = Person.objects.get_or_create(
Tom Teichler's avatar
Tom Teichler committed
                defaults={
                    "mobile_number": cleaned_data_guardians["guardian_mobile_number"],
                },
Tom Teichler's avatar
Tom Teichler committed
                first_name=cleaned_data_guardians["guardian_first_name"],
                last_name=cleaned_data_guardians["guardian_last_name"],
Tom Teichler's avatar
Tom Teichler committed
                email=cleaned_data_guardians["guardian_email"],
            )

Tom Teichler's avatar
Tom Teichler committed
            person.guardians.add(guardian)
Tom Teichler's avatar
Tom Teichler committed
            person.save()

        if cleaned_data_email:
            _email.person = person
            _email.save()

        registration = EventRegistration.objects.create(
            managed_by_app_label="",
Tom Teichler's avatar
Tom Teichler committed
            event=event,
            person=person,
            medical_information=cleaned_data_additional["medical_information"],
            donation=cleaned_data_financial["donation"],
            school=cleaned_data_contact_details["school"],
            school_class=cleaned_data_contact_details["school_class"],
            school_place=cleaned_data_contact_details["school_place"],
Tom Teichler's avatar
Tom Teichler committed
        )
Hangzhi Yu's avatar
Hangzhi Yu committed
        for field in event.additional_fields.all():
            registration.extended_data[
                slugify(field.title).replace("-", "_")
            ] = cleaned_data_additional[field.title]

        for field in cleaned_data_consent:
            if not field.startswith("consent_"):
                continue
            pk = int(field.split("_")[1])
            term = Terms.objects.get(id=pk)
            registration.accepted_terms.add(term)
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
        registration.save()

Tom Teichler's avatar
Tom Teichler committed
        if cleaned_data_financial["voucher_code"]:
            vouchers = Voucher.objects.filter(
                person=person, event=event, used=False, code=cleaned_data_financial["voucher_code"]
            )
            if vouchers:
                voucher = vouchers.first()
Tom Teichler's avatar
Tom Teichler committed
                registration.voucher = voucher
Tom Teichler's avatar
Tom Teichler committed
                with reversion.create_revision():
Tom Teichler's avatar
Tom Teichler committed
                    registration.save()
            else:
                messages.error(self.request, _("You entered an invalid voucher code!"))

        invoice = registration.get_invoice()
        invoice.variant = cleaned_data_financial["payment_method"]
        invoice.save()

Tom Teichler's avatar
Tom Teichler committed
        context = {}
        context["registration"] = registration

        send_templated_mail(
Tom Teichler's avatar
Tom Teichler committed
            template_name="event_registered",
            from_email=get_site_preferences()["mail__address"],
            recipient_list=[get_site_preferences()["paweljong__event_notification_recipient"]],
Tom Teichler's avatar
Tom Teichler committed
            headers={
                "reply_to": [
                    person.email,
                    person.guardians.first().email,
                ],
                "X-Zammad-Customer-Email": person.email,
Tom Teichler's avatar
Tom Teichler committed
            },
            context=context,
        )

        messages.success(
            self.request,
            _(
                "You have successfully registered for the event. Please give us "
                "up to two days to process your registration. You will then "
                "receive an email from us."
            ),
        )

        act = Activity(
Tom Teichler's avatar
Tom Teichler committed
            title=_("You registered for an event"),
            description=_("You registered for the event %s" % event.display_name),
            app="Paweljong",
Tom Teichler's avatar
Tom Teichler committed
            user=person,
        )

Tom Teichler's avatar
Tom Teichler committed
        return redirect("do_payment", invoice.token)
class EventFullView(PermissionRequiredMixin, DetailView):
Tom Teichler's avatar
Tom Teichler committed
    model = Event
    slug_field = "slug"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event/full.html"
    object_context_name = "event"
    permission_required = "paweljong.view_event_rule"
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context["can_register"] = context["event"].can_register(request=self.request)
        context["is_authenticated"] = self.request.user.is_authenticated
        context["individual_cost"] = context["event"].individual_cost(request=self.request)

        return context

class RegisterEventStart(PermissionRequiredMixin, DetailView):
    model = Event
    slug_field = "slug"
    template_name = "paweljong/event/register_start.html"
    object_context_name = "event"
    permission_required = "paweljong.view_event_rule"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
        context["can_register"] = context["event"].can_register(request=self.request)
        return context
Tom Teichler's avatar
Tom Teichler committed

Tom Teichler's avatar
Tom Teichler committed
class TermListView(PermissionRequiredMixin, SingleTableView):
    """Table of all terms."""

    model = Terms
    table_class = TermsTable
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.view_terms_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/term/list.html"


@method_decorator(never_cache, name="dispatch")
class TermCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for terms."""

    model = Terms
    form_class = EditTermForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_terms_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/term/create.html"
    success_url = reverse_lazy("terms")
    success_message = _("The term has been created.")


@method_decorator(never_cache, name="dispatch")
class TermEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for terms."""

    model = Terms
    form_class = EditTermForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_terms_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/term/edit.html"
    success_url = reverse_lazy("terms")
    success_message = _("The term has been saved.")


class UpcomingEventsRSSFeed(Feed):
    """RSS feed for published, upcoming events."""

    def title(self):
        return _("Upcoming events")

    def link(self):
        return reverse("index")

    def feed_url(self):
        return reverse("upcoming_events_rss_feed")

    def description(self):
        return _("Announcement feed of all upcoming events")

    def ttl(self):
        date_event = Event.upcoming_published_events().order_by("-date_event").first().date_event
Nik | Klampfradler's avatar
Nik | Klampfradler committed
        date_now = timezone.now().date()

        return (date_event - date_now).seconds

    def items(self):
        return Event.upcoming_published_events()

    def item_title(self, item):
        return item.display_name

    def item_description(self, item):
        return item.description
class AccountRegisterStart(TemplateView):
    template_name = "paweljong/register_start.html"


class InfoMailingListView(PermissionRequiredMixin, SingleTableView):
    """Table of all info mailings."""

    model = InfoMailing
    table_class = InfoMailingsTable
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.view_info_mailings_rule"
    template_name = "paweljong/info_mailing/list.html"


@method_decorator(never_cache, name="dispatch")
class InfoMailingCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for info mailings."""

    model = InfoMailing
    form_class = EditInfoMailingForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_info_mailing_rule"
    template_name = "paweljong/info_mailing/create.html"
    success_url = reverse_lazy("info_mailings")
    success_message = _("The info mailing has been created.")


@method_decorator(never_cache, name="dispatch")
class InfoMailingEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for info mailings."""

    model = InfoMailing
    form_class = EditInfoMailingForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_info_mailing_rule"
    template_name = "paweljong/info_mailing/edit.html"
    success_url = reverse_lazy("info_mailings")
    success_message = _("The info mailing has been saved.")


class InfoMailingDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
    """Delete view for info mailings."""

    model = InfoMailing
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.delete_info_mailing_rule"
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("info_mailings")
    success_message = _("The info mailing has been deleted.")


class SendMailFromRegistration(PermissionRequiredMixin, FormView):
    template_name = "paweljong/event_registration/notification.html"
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.send_notification_mail_rule"
    form_class = RegistrationNotificationForm
Tom Teichler's avatar
Tom Teichler committed
    success_url = reverse_lazy("manage_events")

    def form_valid(self, form):
        registration = EventRegistration.objects.get(id=self.kwargs["pk"])

        context = {}
        recipient_list = []
        context["subject"] = form.cleaned_data["subject"]
        context["registration"] = registration
        context["body"] = form.cleaned_data["text"]

        if form.cleaned_data["reply_to"]:
            reply_to = form.cleaned_data["reply_to"]
        else:
            reply_to = form.cleaned_data["sender"]
        if form.cleaned_data["send_to_person"]:
            recipient_list.append(registration.person.email)
        if form.cleaned_data["send_to_guardians"]:
            recipient_list.append(registration.person.guardians.first().email)

        send_templated_mail(
            template_name="event_notification",
            from_email=get_site_preferences()["mail__address"],
            recipient_list=recipient_list,
            headers={
                "reply_to": reply_to,
            },
            context=context,
        )

        return super().form_valid(self)


class RegistrationStateListView(PermissionRequiredMixin, SingleTableView):
    """Table of all terms."""

    model = RegistrationState
    table_class = RegistrationStatesTable
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.view_registration_states_rule"
    template_name = "paweljong/registration_state/list.html"


@method_decorator(never_cache, name="dispatch")
class RegistrationStateCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for terms."""

    model = RegistrationState
    form_class = RegistrationStatesForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.create_registration_states_rule"
    template_name = "paweljong/registration_state/create.html"
    success_url = reverse_lazy("registration_states")
    success_message = _("The term has been created.")


@method_decorator(never_cache, name="dispatch")
class RegistrationStateEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for terms."""

    model = RegistrationState
    form_class = RegistrationStatesForm
Tom Teichler's avatar
Tom Teichler committed
    permission_required = "paweljong.change_registration_states_rule"
    template_name = "paweljong/registration_state/edit.html"
    success_url = reverse_lazy("registration_states")
    success_message = _("The term has been saved.")
class RetractRegistration(PermissionRequiredMixin, View):
    permission_required = "paweljong.can_retract_registration_rule"

Tom Teichler's avatar
Tom Teichler committed
    def get_object(self, *args, **kwargs):
        return EventRegistration.objects.get(id=self.kwargs["pk"])

    def get(self, *args, **kwargs):
Tom Teichler's avatar
Tom Teichler committed
        registration = self.get_object()
Tom Teichler's avatar
Tom Teichler committed

        registration.retract()
        messages.success(self.request, _("Registration successfully retracted."))

Tom Teichler's avatar
Tom Teichler committed
        return redirect("event_detail_by_name", slug=registration.event.slug)
Tom Teichler's avatar
Tom Teichler committed
class EventDetailView(PermissionRequiredMixin, DetailView):
    """Detail view for an event instance."""

    context_object_name = "event"
    permission_required = "paweljong.view_event_detail_rule"
Tom Teichler's avatar
Tom Teichler committed
    template_name = "paweljong/event/detail.html"
    model = Event
    slug_field = "slug"

    def get_queryset(self):
        return Event.objects.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        registrations = EventRegistration.objects.filter(event=self.object)
        registrations_filter = EventRegistrationFilter(self.request.GET, queryset=registrations)
        context["registrations_filter"] = registrations_filter

        # Registrations table
        registrations_table = EventRegistrationsTable(registrations_filter.qs)
Tom Teichler's avatar
Tom Teichler committed
        RequestConfig(self.request).configure(registrations_table)
        context["registrations_table"] = registrations_table

        # Child groups table
        child_groups = self.object.linked_group.child_groups.all()
Tom Teichler's avatar
Tom Teichler committed
        child_groups_table = ChildGroupsTable(child_groups)
Tom Teichler's avatar
Tom Teichler committed
        RequestConfig(self.request).configure(child_groups_table)
        context["child_groups_table"] = child_groups_table

Hangzhi Yu's avatar
Hangzhi Yu committed
        # Additional fields table
        additional_fields = self.object.additional_fields.all()
        additional_fields_table = EventAdditionalFieldsTable(additional_fields)
Hangzhi Yu's avatar
Hangzhi Yu committed
        RequestConfig(self.request).configure(additional_fields_table)
        context["additional_fields_table"] = additional_fields_table

Tom Teichler's avatar
Tom Teichler committed
        return context
Tom Teichler's avatar
Tom Teichler committed
class PersonGroupView(PermissionRequiredMixin, FormView):
    template_name = "paweljong/event/persons_group.html"
    permission_required = "paweljong.add_persons_to_group_rule"
    form_class = PersonGroupFormPerson
Tom Teichler's avatar
Tom Teichler committed
    def form_valid(self, form):
        group = Group.objects.get(id=self.kwargs["pk"])
Tom Teichler's avatar
Tom Teichler committed
        try:
            person = Person.objects.get(user__username=form.cleaned_data["username"])
            group.members.add(person)
            messages.success(self.request, _(f"Person {person} added successfully!"))
        except Person.DoesNotExist:
            messages.error(self.request, _("Person does not exist!"))