mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 09:12:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1544 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1544 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | 
						|
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
						|
 | 
						|
import os
 | 
						|
import shutil
 | 
						|
import subprocess
 | 
						|
from datetime import date
 | 
						|
from tempfile import mkdtemp
 | 
						|
 | 
						|
from django.conf import settings
 | 
						|
from django.contrib import messages
 | 
						|
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
						|
from django.contrib.auth.models import User
 | 
						|
from django.core.exceptions import PermissionDenied
 | 
						|
from django.db import transaction
 | 
						|
from django.db.models import Q, Count, Case, When, Value, IntegerField, F
 | 
						|
from django.db.models.functions.text import Lower
 | 
						|
from django import forms
 | 
						|
from django.http import HttpResponse, Http404
 | 
						|
from django.shortcuts import redirect
 | 
						|
from django.template.loader import render_to_string
 | 
						|
from django.urls import reverse_lazy
 | 
						|
from django.views import View
 | 
						|
from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView
 | 
						|
from django.utils.translation import gettext_lazy as _
 | 
						|
from django.views.generic.edit import BaseFormView, DeleteView
 | 
						|
from django_tables2 import SingleTableView, MultiTableMixin
 | 
						|
from api.viewsets import is_regex
 | 
						|
from member.models import Membership, Club
 | 
						|
from note.models import Transaction, NoteClub, Alias, SpecialTransaction
 | 
						|
from note.tables import HistoryTable
 | 
						|
from note_kfet.settings import BASE_DIR
 | 
						|
from permission.backends import PermissionBackend
 | 
						|
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
 | 
						|
 | 
						|
from .forms.registration import WEIChooseBusForm
 | 
						|
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
 | 
						|
from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMembership1AForm, \
 | 
						|
    WEIMembershipForm, CurrentSurvey
 | 
						|
from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \
 | 
						|
    WEIRegistration1ATable, WEIMembershipTable
 | 
						|
 | 
						|
 | 
						|
class CurrentWEIDetailView(LoginRequiredMixin, RedirectView):
 | 
						|
    def get_redirect_url(self, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.filter(membership_start__lte=date.today()).order_by('date_start')
 | 
						|
        if wei.exists():
 | 
						|
            wei = wei.last()
 | 
						|
            return reverse_lazy('wei:wei_detail', args=(wei.pk,))
 | 
						|
        else:
 | 
						|
            return reverse_lazy('wei:wei_list')
 | 
						|
 | 
						|
 | 
						|
class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
						|
    """
 | 
						|
    List existing WEI
 | 
						|
    """
 | 
						|
    model = WEIClub
 | 
						|
    table_class = WEITable
 | 
						|
    ordering = '-year'
 | 
						|
    extra_context = {"title": _("Search WEI")}
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["can_create_wei"] = PermissionBackend.check_perm(self.request, "wei.add_weiclub", WEIClub(
 | 
						|
            name="",
 | 
						|
            email="weiclub@example.com",
 | 
						|
            year=0,
 | 
						|
            date_start=date.today(),
 | 
						|
            date_end=date.today(),
 | 
						|
        ))
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEICreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Create WEI
 | 
						|
    """
 | 
						|
 | 
						|
    model = WEIClub
 | 
						|
    form_class = WEIForm
 | 
						|
    extra_context = {"title": _("Create WEI")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        return WEIClub(
 | 
						|
            name="",
 | 
						|
            email="weiclub@example.com",
 | 
						|
            year=0,
 | 
						|
            date_start=date.today(),
 | 
						|
            date_end=date.today(),
 | 
						|
        )
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        form.instance.requires_membership = True
 | 
						|
        form.instance.parent_club = Club.objects.get(name="Kfet")
 | 
						|
        ret = super().form_valid(form)
 | 
						|
        NoteClub.objects.create(club=form.instance)
 | 
						|
        return ret
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, DetailView):
 | 
						|
    """
 | 
						|
    View WEI information
 | 
						|
    """
 | 
						|
    model = WEIClub
 | 
						|
    context_object_name = "club"
 | 
						|
    extra_context = {"title": _("WEI Detail")}
 | 
						|
 | 
						|
    tables = [
 | 
						|
        lambda data: HistoryTable(data, prefix="history-"),
 | 
						|
        lambda data: WEIMembershipTable(data, prefix="membership-"),
 | 
						|
        lambda data: WEIRegistrationTable(data, prefix="pre-registration-"),
 | 
						|
        lambda data: BusTable(data, prefix="bus-"),
 | 
						|
    ]
 | 
						|
    paginate_by = 20   # number of rows in tables
 | 
						|
 | 
						|
    def get_tables_data(self):
 | 
						|
        club = self.object
 | 
						|
        club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note)) \
 | 
						|
            .filter(PermissionBackend.filter_queryset(self.request, Transaction, "view")) \
 | 
						|
            .order_by('-created_at', '-id')
 | 
						|
        club_member = WEIMembership.objects.filter(
 | 
						|
            club=club,
 | 
						|
            date_end__gte=date.today(),
 | 
						|
        ).filter(PermissionBackend.filter_queryset(self.request, WEIMembership, "view"))
 | 
						|
        pre_registrations = WEIRegistration.objects.filter(
 | 
						|
            PermissionBackend.filter_queryset(self.request, WEIRegistration, "view")).filter(
 | 
						|
            membership=None,
 | 
						|
            wei=club
 | 
						|
        )
 | 
						|
        # Annotate the query to be able to sort registrations on validate status
 | 
						|
        pre_registrations = pre_registrations.annotate(
 | 
						|
            deposit=Case(
 | 
						|
                When(deposit_type='note', then=F('wei__deposit_amount')),
 | 
						|
                default=Value(0),
 | 
						|
                output_field=IntegerField()
 | 
						|
            )
 | 
						|
        ).annotate(
 | 
						|
            total_fee=F('fee') + F('deposit')
 | 
						|
        ).annotate(
 | 
						|
            validate_status=Case(
 | 
						|
                When(total_fee__gt=F('user__note__balance'), then=Value(2)),
 | 
						|
                When(first_year=True, then=Value(1)),
 | 
						|
                default=Value(0),
 | 
						|
                output_field=IntegerField(),
 | 
						|
            )
 | 
						|
        )
 | 
						|
        buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request, Bus, "view")) \
 | 
						|
            .filter(wei=self.object).annotate(count=Count("memberships")).order_by("name")
 | 
						|
        return [club_transactions, club_member, pre_registrations, buses, ]
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
 | 
						|
        club = context["club"]
 | 
						|
 | 
						|
        tables = context["tables"]
 | 
						|
        for name, table in zip(["history_list", "member_list", "pre_registrations", "buses"], tables):
 | 
						|
            context[name] = table
 | 
						|
 | 
						|
        my_registration = WEIRegistration.objects.filter(wei=club, user=self.request.user)
 | 
						|
        if my_registration.exists():
 | 
						|
            my_registration = my_registration.get()
 | 
						|
            context["survey_complete"] = CurrentSurvey(my_registration).is_complete()
 | 
						|
        else:
 | 
						|
            my_registration = None
 | 
						|
        context["my_registration"] = my_registration
 | 
						|
 | 
						|
        random_user = User.objects.filter(~Q(wei__wei__in=[club])).first()
 | 
						|
 | 
						|
        if random_user is None:
 | 
						|
            # This case occurs when all users are registered to the WEI.
 | 
						|
            # Don't worry, Pikachu never went to the WEI.
 | 
						|
            # This bug can arrive only in dev mode.
 | 
						|
            context["can_add_first_year_member"] = True
 | 
						|
            context["can_add_any_member"] = True
 | 
						|
        else:
 | 
						|
            # Check if the user has the right to create a registration of a random first year member.
 | 
						|
            empty_fy_registration = WEIRegistration(
 | 
						|
                wei=club,
 | 
						|
                user=random_user,
 | 
						|
                first_year=True,
 | 
						|
                birth_date="1970-01-01",
 | 
						|
                gender="No",
 | 
						|
                emergency_contact_name="No",
 | 
						|
                emergency_contact_phone="No",
 | 
						|
            )
 | 
						|
            context["can_add_first_year_member"] = PermissionBackend \
 | 
						|
                .check_perm(self.request, "wei.add_weiregistration", empty_fy_registration)
 | 
						|
 | 
						|
            # Check if the user has the right to create a registration of a random old member.
 | 
						|
            empty_old_registration = WEIRegistration(
 | 
						|
                wei=club,
 | 
						|
                user=User.objects.filter(~Q(wei__wei__in=[club])).first(),
 | 
						|
                first_year=False,
 | 
						|
                birth_date="1970-01-01",
 | 
						|
                gender="No",
 | 
						|
                emergency_contact_name="No",
 | 
						|
                emergency_contact_phone="No",
 | 
						|
            )
 | 
						|
            context["can_add_any_member"] = PermissionBackend \
 | 
						|
                .check_perm(self.request, "wei.add_weiregistration", empty_old_registration)
 | 
						|
 | 
						|
        empty_bus = Bus(
 | 
						|
            wei=club,
 | 
						|
            name="",
 | 
						|
        )
 | 
						|
        context["can_add_bus"] = PermissionBackend.check_perm(self.request, "wei.add_bus", empty_bus)
 | 
						|
 | 
						|
        context["not_first_year"] = WEIMembership.objects.filter(user=self.request.user).exists()
 | 
						|
 | 
						|
        context["registration_validated"] = WEIMembership.objects.filter(registration=my_registration).exists() if my_registration else False
 | 
						|
 | 
						|
        qs = WEIMembership.objects.filter(club=club, registration__first_year=True, bus__isnull=True)
 | 
						|
        context["can_validate_1a"] = PermissionBackend.check_perm(
 | 
						|
            self.request, "wei.change_weimembership_bus", qs.first()) if qs.exists() else False
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
						|
    """
 | 
						|
    List all WEI memberships
 | 
						|
    """
 | 
						|
    model = WEIMembership
 | 
						|
    table_class = WEIMembershipTable
 | 
						|
    extra_context = {"title": _("View members of the WEI")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_queryset(self, **kwargs):
 | 
						|
        qs = super().get_queryset(**kwargs).filter(club=self.club).distinct()
 | 
						|
 | 
						|
        pattern = self.request.GET.get("search", "")
 | 
						|
 | 
						|
        if not pattern:
 | 
						|
            return qs.none()
 | 
						|
 | 
						|
        # Check if this is a valid regex. If not, we won't check regex
 | 
						|
        valid_regex = is_regex(pattern)
 | 
						|
        suffix_alias = "__iregex" if valid_regex else "__istartswith"
 | 
						|
        suffix = "__iregex" if valid_regex else "__icontains"
 | 
						|
        prefix = "^" if valid_regex else ""
 | 
						|
        qs = qs.filter(
 | 
						|
            Q(**{f"user__first_name{suffix}": pattern})
 | 
						|
            | Q(**{f"user__last_name{suffix}": pattern})
 | 
						|
            | Q(**{f"user__note__alias__name{suffix_alias}": prefix + pattern})
 | 
						|
            | Q(**{f"user__note__alias__normalized_name{suffix_alias}": prefix + Alias.normalize(pattern)})
 | 
						|
            | Q(**{f"bus__name{suffix}": pattern})
 | 
						|
            | Q(**{f"team__name{suffix}": pattern})
 | 
						|
        )
 | 
						|
 | 
						|
        return qs
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.club
 | 
						|
        context["title"] = _("Find WEI Membership")
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
						|
    """
 | 
						|
    List all non-validated WEI registrations.
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    table_class = WEIRegistrationTable
 | 
						|
    extra_context = {"title": _("View registrations to the WEI")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_queryset(self, **kwargs):
 | 
						|
        qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None).distinct()
 | 
						|
        # Annotate the query to be able to sort registrations on validate status
 | 
						|
        qs = qs.annotate(
 | 
						|
            deposit=Case(
 | 
						|
                When(deposit_type='note', then=F('wei__deposit_amount')),
 | 
						|
                default=Value(0),
 | 
						|
                output_field=IntegerField()
 | 
						|
            )
 | 
						|
        ).annotate(
 | 
						|
            total_fee=F('fee') + F('deposit')
 | 
						|
        ).annotate(
 | 
						|
            validate_status=Case(
 | 
						|
                When(total_fee__gt=F('user__note__balance'), then=Value(2)),
 | 
						|
                When(first_year=True, then=Value(1)),
 | 
						|
                default=Value(0),
 | 
						|
                output_field=IntegerField(),
 | 
						|
            )
 | 
						|
        )
 | 
						|
 | 
						|
        pattern = self.request.GET.get("search", "")
 | 
						|
 | 
						|
        if pattern:
 | 
						|
            # Check if this is a valid regex. If not, we won't check regex
 | 
						|
            valid_regex = is_regex(pattern)
 | 
						|
            suffix_alias = "__iregex" if valid_regex else "__istartswith"
 | 
						|
            suffix = "__iregex" if valid_regex else "__icontains"
 | 
						|
            prefix = "^" if valid_regex else ""
 | 
						|
            qs = qs.filter(
 | 
						|
                Q(**{f"user__first_name{suffix}": pattern})
 | 
						|
                | Q(**{f"user__last_name{suffix}": pattern})
 | 
						|
                | Q(**{f"user__note__alias__name{suffix_alias}": prefix + pattern})
 | 
						|
                | Q(**{f"user__note__alias__normalized_name{suffix_alias}": prefix + Alias.normalize(pattern)})
 | 
						|
            )
 | 
						|
 | 
						|
        return qs
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.club
 | 
						|
        context["title"] = _("Find WEI Registration")
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    Update the information of the WEI.
 | 
						|
    """
 | 
						|
    model = WEIClub
 | 
						|
    context_object_name = "club"
 | 
						|
    form_class = WEIForm
 | 
						|
    extra_context = {"title": _("Update the WEI")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object()
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a past WEI
 | 
						|
        # But we can update it while it is not officially opened
 | 
						|
        if today > wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class BusCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Create Bus
 | 
						|
    """
 | 
						|
    model = Bus
 | 
						|
    form_class = BusForm
 | 
						|
    extra_context = {"title": _("Create new bus")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return Bus(
 | 
						|
            wei=wei,
 | 
						|
            name="",
 | 
						|
        )
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        today = date.today()
 | 
						|
        # We can't add a bus once the WEI is started
 | 
						|
        if today >= wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["wei"].initial = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class BusUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    Update Bus
 | 
						|
    """
 | 
						|
    model = Bus
 | 
						|
    form_class = BusForm
 | 
						|
    extra_context = {"title": _("Update bus")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object().wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a bus once the WEI is started
 | 
						|
        if today >= wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
        context["information"] = CurrentSurvey.get_algorithm_class().get_bus_information(self.object)
 | 
						|
        self.object.save()
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["wei"].disabled = True
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
						|
    """
 | 
						|
    Manage Bus
 | 
						|
    """
 | 
						|
    model = Bus
 | 
						|
    extra_context = {"title": _("Manage bus")}
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
 | 
						|
        bus = self.object
 | 
						|
        teams = BusTeam.objects.filter(PermissionBackend.filter_queryset(self.request, BusTeam, "view")) \
 | 
						|
            .filter(bus=bus).annotate(count=Count("memberships")).order_by("name")
 | 
						|
        teams_table = BusTeamTable(data=teams, prefix="team-")
 | 
						|
        context["teams"] = teams_table
 | 
						|
 | 
						|
        memberships = WEIMembership.objects.filter(PermissionBackend.filter_queryset(
 | 
						|
            self.request, WEIMembership, "view")).filter(bus=bus)
 | 
						|
        memberships_table = WEIMembershipTable(data=memberships, prefix="membership-")
 | 
						|
        memberships_table.paginate(per_page=20, page=self.request.GET.get("membership-page", 1))
 | 
						|
        context["memberships"] = memberships_table
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class BusTeamCreateView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Create BusTeam
 | 
						|
    """
 | 
						|
    model = BusTeam
 | 
						|
    form_class = BusTeamForm
 | 
						|
    extra_context = {"title": _("Create new team")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        bus = Bus.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return BusTeam(
 | 
						|
            name="",
 | 
						|
            bus=bus,
 | 
						|
            color=0,
 | 
						|
        )
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"])
 | 
						|
        today = date.today()
 | 
						|
        # We can't add a team once the WEI is started
 | 
						|
        if today >= wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        bus = Bus.objects.get(pk=self.kwargs["pk"])
 | 
						|
        context["club"] = bus.wei
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["bus"].initial = Bus.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
    def get_template_names(self):
 | 
						|
        names = super().get_template_names()
 | 
						|
        return names
 | 
						|
 | 
						|
 | 
						|
class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    Update Bus team
 | 
						|
    """
 | 
						|
    model = BusTeam
 | 
						|
    form_class = BusTeamForm
 | 
						|
    extra_context = {"title": _("Update team")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object().bus.wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a bus once the WEI is started
 | 
						|
        if today >= wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.bus.wei
 | 
						|
        context["bus"] = self.object.bus
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["bus"].disabled = True
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
    def get_template_names(self):
 | 
						|
        names = super().get_template_names()
 | 
						|
        return names
 | 
						|
 | 
						|
 | 
						|
class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
						|
    """
 | 
						|
    Manage Bus team
 | 
						|
    """
 | 
						|
    model = BusTeam
 | 
						|
    extra_context = {"title": _("Manage WEI team")}
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["bus"] = self.object.bus
 | 
						|
        context["club"] = self.object.bus.wei
 | 
						|
 | 
						|
        memberships = WEIMembership.objects.filter(PermissionBackend.filter_queryset(
 | 
						|
            self.request, WEIMembership, "view")).filter(team=self.object)
 | 
						|
        memberships_table = WEIMembershipTable(data=memberships, prefix="membership-")
 | 
						|
        memberships_table.paginate(per_page=20, page=self.request.GET.get("membership-page", 1))
 | 
						|
        context["memberships"] = memberships_table
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Register a new user to the WEI
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    form_class = WEIRegistrationForm
 | 
						|
    extra_context = {"title": _("Register first year student to the WEI")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        if "myself" in self.request.path:
 | 
						|
            user = self.request.user
 | 
						|
        else:
 | 
						|
            # To avoid unique validation issues, we use an account that can't join the WEI.
 | 
						|
            # In development mode, the note account may not exist, we use a random user (may fail)
 | 
						|
            user = User.objects.get(username="note") \
 | 
						|
                if User.objects.filter(username="note").exists() else User.objects.first()
 | 
						|
        return WEIRegistration(
 | 
						|
            wei=wei,
 | 
						|
            user=user,
 | 
						|
            first_year=True,
 | 
						|
            birth_date="1970-01-01",
 | 
						|
            gender="No",
 | 
						|
            emergency_contact_name="No",
 | 
						|
            emergency_contact_phone="No",
 | 
						|
        )
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        today = date.today()
 | 
						|
        # We can't register someone once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        # Don't register twice
 | 
						|
        if 'myself' in self.request.path and not self.request.user.is_anonymous \
 | 
						|
                and WEIRegistration.objects.filter(wei=wei, user=self.request.user).exists():
 | 
						|
            obj = WEIRegistration.objects.get(wei=wei, user=self.request.user)
 | 
						|
            return redirect(reverse_lazy('wei:wei_update_registration', args=(obj.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context['title'] = _("Register 1A")
 | 
						|
        context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        if "myself" in self.request.path:
 | 
						|
            context["form"].fields["user"].disabled = True
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["user"].initial = self.request.user
 | 
						|
 | 
						|
        # Cacher les champs pendant l'inscription initiale
 | 
						|
        if "first_year" in form.fields:
 | 
						|
            del form.fields["first_year"]
 | 
						|
        if "deposit_given" in form.fields:
 | 
						|
            del form.fields["deposit_given"]
 | 
						|
        if "information_json" in form.fields:
 | 
						|
            del form.fields["information_json"]
 | 
						|
        if "deposit_type" in form.fields:
 | 
						|
            del form.fields["deposit_type"]
 | 
						|
 | 
						|
        if "soge_credit" in form.fields:
 | 
						|
            form.fields["soge_credit"].help_text = _('Check if you will open a Société Générale account')
 | 
						|
        return form
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        form.instance.first_year = True
 | 
						|
 | 
						|
        if not form.instance.pk:
 | 
						|
            # Check if the user is not already registered to the WEI
 | 
						|
            if WEIRegistration.objects.filter(wei=form.instance.wei, user=form.instance.user).exists():
 | 
						|
                form.add_error('user', _("This user is already registered to this WEI."))
 | 
						|
                return self.form_invalid(form)
 | 
						|
 | 
						|
            # Check if the user can be in her/his first year (yeah, no cheat)
 | 
						|
            if WEIRegistration.objects.filter(user=form.instance.user).exists():
 | 
						|
                form.add_error('user', _("This user can't be in her/his first year since he/she has already"
 | 
						|
                                         " participated to a WEI."))
 | 
						|
                return self.form_invalid(form)
 | 
						|
 | 
						|
        if 'treasury' in settings.INSTALLED_APPS:
 | 
						|
            from treasury.models import SogeCredit
 | 
						|
            form.instance.soge_credit = \
 | 
						|
                form.instance.soge_credit \
 | 
						|
                or SogeCredit.objects.filter(user=form.instance.user, credit_transaction__valid=False).exists()
 | 
						|
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Register an old user to the WEI
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    form_class = WEIRegistrationForm
 | 
						|
    extra_context = {"title": _("Register old student to the WEI")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        if "myself" in self.request.path:
 | 
						|
            user = self.request.user
 | 
						|
        else:
 | 
						|
            # To avoid unique validation issues, we use an account that can't join the WEI.
 | 
						|
            # In development mode, the note account may not exist, we use a random user (may fail)
 | 
						|
            user = User.objects.get(username="note") \
 | 
						|
                if User.objects.filter(username="note").exists() else User.objects.first()
 | 
						|
        return WEIRegistration(
 | 
						|
            wei=wei,
 | 
						|
            user=user,
 | 
						|
            first_year=True,
 | 
						|
            birth_date="1970-01-01",
 | 
						|
            gender="No",
 | 
						|
            emergency_contact_name="No",
 | 
						|
            emergency_contact_phone="No",
 | 
						|
        )
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        today = date.today()
 | 
						|
        # We can't register someone once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        # Don't register twice
 | 
						|
        if 'myself' in self.request.path and not self.request.user.is_anonymous \
 | 
						|
                and WEIRegistration.objects.filter(wei=wei, user=self.request.user).exists():
 | 
						|
            obj = WEIRegistration.objects.get(wei=wei, user=self.request.user)
 | 
						|
            return redirect(reverse_lazy('wei:wei_update_registration', args=(obj.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context['title'] = _("Register 2A+")
 | 
						|
        context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
 | 
						|
        if "myself" in self.request.path:
 | 
						|
            context["form"].fields["user"].disabled = True
 | 
						|
 | 
						|
        choose_bus_form = WEIChooseBusForm(self.request.POST if self.request.POST else None)
 | 
						|
        choose_bus_form.fields["bus"].queryset = Bus.objects.filter(wei=context["club"]).order_by('name')
 | 
						|
        choose_bus_form.fields["team"].queryset = BusTeam.objects.filter(bus__wei=context["club"])\
 | 
						|
            .order_by('bus__name', 'name')
 | 
						|
        context['membership_form'] = choose_bus_form
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["user"].initial = self.request.user
 | 
						|
        if "soge_credit" in form.fields:
 | 
						|
            form.fields["soge_credit"].help_text = _('Check if you will open a Société Générale account')
 | 
						|
 | 
						|
        if "myself" in self.request.path and self.request.user.profile.soge:
 | 
						|
            form.fields["soge_credit"].disabled = True
 | 
						|
            form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.")
 | 
						|
 | 
						|
        # Cacher les champs pendant l'inscription initiale
 | 
						|
        if "first_year" in form.fields:
 | 
						|
            del form.fields["first_year"]
 | 
						|
        if "deposit_given" in form.fields:
 | 
						|
            del form.fields["deposit_given"]
 | 
						|
        if "information_json" in form.fields:
 | 
						|
            del form.fields["information_json"]
 | 
						|
 | 
						|
        # S'assurer que le champ deposit_type est obligatoire
 | 
						|
        if "deposit_type" in form.fields:
 | 
						|
            form.fields["deposit_type"].required = True
 | 
						|
            form.fields["deposit_type"].help_text = _("Choose how you want to pay the deposit")
 | 
						|
            form.fields["deposit_type"].widget = forms.RadioSelect(choices=form.fields["deposit_type"].choices)
 | 
						|
 | 
						|
        return form
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        form.instance.first_year = False
 | 
						|
 | 
						|
        if not form.instance.pk:
 | 
						|
            # Check if the user is not already registered to the WEI
 | 
						|
            if WEIRegistration.objects.filter(wei=form.instance.wei, user=form.instance.user).exists():
 | 
						|
                form.add_error('user', _("This user is already registered to this WEI."))
 | 
						|
                return self.form_invalid(form)
 | 
						|
 | 
						|
        choose_bus_form = WEIChooseBusForm(self.request.POST)
 | 
						|
        if not choose_bus_form.is_valid():
 | 
						|
            return self.form_invalid(form)
 | 
						|
 | 
						|
        information = form.instance.information
 | 
						|
        information["preferred_bus_pk"] = [bus.pk for bus in choose_bus_form.cleaned_data["bus"]]
 | 
						|
        information["preferred_bus_name"] = [bus.name for bus in choose_bus_form.cleaned_data["bus"]]
 | 
						|
        information["preferred_team_pk"] = [team.pk for team in choose_bus_form.cleaned_data["team"]]
 | 
						|
        information["preferred_team_name"] = [team.name for team in choose_bus_form.cleaned_data["team"]]
 | 
						|
        information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
 | 
						|
        information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
 | 
						|
        form.instance.information = information
 | 
						|
 | 
						|
        # Sauvegarder le type de caution
 | 
						|
        form.instance.deposit_type = form.cleaned_data["deposit_type"]
 | 
						|
        form.instance.save()
 | 
						|
 | 
						|
        if 'treasury' in settings.INSTALLED_APPS:
 | 
						|
            from treasury.models import SogeCredit
 | 
						|
            form.instance.soge_credit = \
 | 
						|
                form.instance.soge_credit \
 | 
						|
                or SogeCredit.objects.filter(user=form.instance.user, credit_transaction__valid=False).exists()
 | 
						|
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
 | 
						|
 | 
						|
 | 
						|
class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    Update a registration for the WEI
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    form_class = WEIRegistrationForm
 | 
						|
    extra_context = {"title": _("Update WEI Registration")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object().wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a registration once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        # Store the validate parameter in the view's state
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
 | 
						|
        if self.object.is_validated:
 | 
						|
            membership_form = self.get_membership_form(instance=self.object.membership,
 | 
						|
                                                       data=self.request.POST)
 | 
						|
            context["membership_form"] = membership_form
 | 
						|
        elif not self.object.first_year and PermissionBackend.check_perm(
 | 
						|
                self.request, "wei.change_weiregistration_information_json", self.object):
 | 
						|
            information = self.object.information
 | 
						|
            d = dict(
 | 
						|
                bus=Bus.objects.filter(pk__in=information["preferred_bus_pk"]).all(),
 | 
						|
                team=BusTeam.objects.filter(pk__in=information["preferred_team_pk"]).all(),
 | 
						|
                roles=WEIRole.objects.filter(pk__in=information["preferred_roles_pk"]).all(),
 | 
						|
            ) if 'preferred_bus_pk' in information else dict()
 | 
						|
            choose_bus_form = WEIChooseBusForm(
 | 
						|
                self.request.POST if self.request.POST else d
 | 
						|
            )
 | 
						|
            choose_bus_form.fields["bus"].queryset = Bus.objects.filter(wei=context["club"])
 | 
						|
            choose_bus_form.fields["team"].queryset = BusTeam.objects.filter(bus__wei=context["club"])
 | 
						|
            context["membership_form"] = choose_bus_form
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        form.fields["user"].disabled = True
 | 
						|
        # The auto-json-format may cause issues with the default field remove
 | 
						|
        if "information_json" in form.fields:
 | 
						|
            del form.fields["information_json"]
 | 
						|
        # Masquer le champ deposit_given pour tout le monde dans le formulaire de modification
 | 
						|
        if "deposit_given" in form.fields:
 | 
						|
            form.fields["deposit_given"].help_text = _("Tick if the deposit check has been given")
 | 
						|
            if self.object.first_year or self.object.deposit_type == 'note':
 | 
						|
                del form.fields["deposit_given"]
 | 
						|
 | 
						|
        # S'assurer que le champ deposit_type est obligatoire pour les 2A+
 | 
						|
        if "deposit_type" in form.fields:
 | 
						|
            if self.object.first_year:
 | 
						|
                del form.fields["deposit_type"]
 | 
						|
            else:
 | 
						|
                form.fields["deposit_type"].required = True
 | 
						|
                form.fields["deposit_type"].help_text = _("Choose how you want to pay the deposit")
 | 
						|
 | 
						|
        if self.object.user.profile.soge:
 | 
						|
            form.fields["soge_credit"].disabled = True
 | 
						|
            form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.")
 | 
						|
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_membership_form(self, data=None, instance=None):
 | 
						|
        registration = self.get_object()
 | 
						|
        membership_form = WEIMembershipForm(data if data else None, instance=instance, wei=registration.wei)
 | 
						|
        del membership_form.fields["credit_type"]
 | 
						|
        del membership_form.fields["credit_amount"]
 | 
						|
        del membership_form.fields["first_name"]
 | 
						|
        del membership_form.fields["last_name"]
 | 
						|
        del membership_form.fields["bank"]
 | 
						|
        for field_name, _field in list(membership_form.fields.items()):
 | 
						|
            if not PermissionBackend.check_perm(
 | 
						|
                    self.request, "wei.change_weimembership_" + field_name, self.object.membership):
 | 
						|
                del membership_form.fields[field_name]
 | 
						|
        return membership_form
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        # If the membership is already validated, then we update the bus and the team (and the roles)
 | 
						|
        if form.instance.is_validated:
 | 
						|
            try:
 | 
						|
                membership = form.instance.membership
 | 
						|
                if membership is None:
 | 
						|
                    raise ValueError(_("No membership found for this registration"))
 | 
						|
 | 
						|
                membership_form = self.get_membership_form(self.request.POST, instance=membership)
 | 
						|
                if not membership_form.is_valid():
 | 
						|
                    return self.form_invalid(form)
 | 
						|
 | 
						|
                # Vérifier que l'utilisateur a la permission de modifier le membership
 | 
						|
                # On vérifie d'abord si l'utilisateur a la permission générale de modification
 | 
						|
                if not self.request.user.has_perm("wei.change_weimembership"):
 | 
						|
                    raise PermissionDenied(_("You don't have the permission to update memberships"))
 | 
						|
 | 
						|
                # On vérifie ensuite les permissions spécifiques pour chaque champ modifié
 | 
						|
                for field_name in membership_form.changed_data:
 | 
						|
                    perm = f"wei.change_weimembership_{field_name}"
 | 
						|
                    if not self.request.user.has_perm(perm):
 | 
						|
                        raise PermissionDenied(_("You don't have the permission to update the field %(field)s") % {'field': field_name})
 | 
						|
 | 
						|
                membership_form.save()
 | 
						|
            except (WEIMembership.DoesNotExist, ValueError, PermissionDenied) as e:
 | 
						|
                form.add_error(None, str(e))
 | 
						|
                return self.form_invalid(form)
 | 
						|
        # If it is not validated and if this is an old member, then we update the choices
 | 
						|
        elif not form.instance.first_year and PermissionBackend.check_perm(
 | 
						|
                self.request, "wei.change_weiregistration_information_json", self.object):
 | 
						|
            choose_bus_form = WEIChooseBusForm(self.request.POST)
 | 
						|
            if not choose_bus_form.is_valid():
 | 
						|
                return self.form_invalid(form)
 | 
						|
            information = form.instance.information
 | 
						|
            information["preferred_bus_pk"] = [bus.pk for bus in choose_bus_form.cleaned_data["bus"]]
 | 
						|
            information["preferred_bus_name"] = [bus.name for bus in choose_bus_form.cleaned_data["bus"]]
 | 
						|
            information["preferred_team_pk"] = [team.pk for team in choose_bus_form.cleaned_data["team"]]
 | 
						|
            information["preferred_team_name"] = [team.name for team in choose_bus_form.cleaned_data["team"]]
 | 
						|
            information["preferred_roles_pk"] = [role.pk for role in choose_bus_form.cleaned_data["roles"]]
 | 
						|
            information["preferred_roles_name"] = [role.name for role in choose_bus_form.cleaned_data["roles"]]
 | 
						|
            form.instance.information = information
 | 
						|
 | 
						|
            if "deposit_type" in form.cleaned_data:
 | 
						|
                form.instance.deposit_type = form.cleaned_data["deposit_type"]
 | 
						|
            form.instance.save()
 | 
						|
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        if self.object.first_year:
 | 
						|
            survey = CurrentSurvey(self.object)
 | 
						|
            if not survey.is_complete():
 | 
						|
                return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
 | 
						|
        return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
 | 
						|
 | 
						|
 | 
						|
class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
 | 
						|
    """
 | 
						|
    Delete a non-validated WEI registration
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    extra_context = {"title": _("Delete WEI registration")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        object = self.get_object()
 | 
						|
        wei = object.wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't delete a registration of a past WEI
 | 
						|
        if today > wei.membership_end:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
 | 
						|
        if not PermissionBackend.check_perm(self.request, "wei.delete_weiregistration", object):
 | 
						|
            raise PermissionDenied(_("You don't have the right to delete this WEI registration."))
 | 
						|
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,))
 | 
						|
 | 
						|
 | 
						|
class WEIValidateRegistrationView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
						|
    """
 | 
						|
    Validate WEI Registration
 | 
						|
    """
 | 
						|
    model = WEIMembership
 | 
						|
    extra_context = {"title": _("Validate WEI registration")}
 | 
						|
 | 
						|
    def get_sample_object(self):
 | 
						|
        """
 | 
						|
        Return a sample object for permission checking
 | 
						|
        """
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return WEIMembership(
 | 
						|
            user=registration.user,
 | 
						|
            club=registration.wei,
 | 
						|
            date_start=registration.wei.date_start,
 | 
						|
            fee=registration.wei.membership_fee_paid if registration.user.profile.paid else registration.wei.membership_fee_unpaid,
 | 
						|
            # Add any fields needed for proper permission checking
 | 
						|
            registration=registration,
 | 
						|
        )
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
 | 
						|
        wei = registration.wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't validate anyone once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        context["registration"] = registration
 | 
						|
        survey = CurrentSurvey(registration)
 | 
						|
        if survey.information.valid:
 | 
						|
            context["suggested_bus"] = survey.information.get_selected_bus()
 | 
						|
        context["club"] = registration.wei
 | 
						|
 | 
						|
        kfet = registration.wei.parent_club
 | 
						|
        bde = kfet.parent_club
 | 
						|
 | 
						|
        context["kfet_member"] = Membership.objects.filter(
 | 
						|
            club__name=kfet.name,
 | 
						|
            user=registration.user,
 | 
						|
            date_start__gte=kfet.membership_start,
 | 
						|
        ).exists()
 | 
						|
        context["bde_member"] = Membership.objects.filter(
 | 
						|
            club__name=bde.name,
 | 
						|
            user=registration.user,
 | 
						|
            date_start__gte=bde.membership_start,
 | 
						|
        ).exists()
 | 
						|
 | 
						|
        fee = registration.fee
 | 
						|
        context["fee"] = fee
 | 
						|
 | 
						|
        # Calculer le montant total nécessaire (frais + caution si transaction)
 | 
						|
        total_needed = fee
 | 
						|
        if registration.deposit_type == 'note':
 | 
						|
            total_needed += registration.wei.deposit_amount
 | 
						|
        context["total_needed"] = total_needed
 | 
						|
 | 
						|
        form = context["form"]
 | 
						|
        if registration.soge_credit:
 | 
						|
            form.fields["credit_amount"].initial = fee
 | 
						|
        else:
 | 
						|
            form.fields["credit_amount"].initial = max(0, fee - registration.user.note.balance)
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_form_class(self):
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        if registration.first_year and 'selected_bus_pk' not in registration.information:
 | 
						|
            return WEIMembership1AForm
 | 
						|
        return WEIMembershipForm
 | 
						|
 | 
						|
    def get_form_kwargs(self):
 | 
						|
        kwargs = super().get_form_kwargs()
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        wei = registration.wei
 | 
						|
        kwargs['wei'] = wei
 | 
						|
        return kwargs
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        form.fields["last_name"].initial = registration.user.last_name
 | 
						|
        form.fields["first_name"].initial = registration.user.first_name
 | 
						|
 | 
						|
        # Ajouter le champ deposit_given uniquement pour les non-première année et le rendre obligatoire
 | 
						|
        if not registration.first_year:
 | 
						|
            if registration.deposit_type == 'check':
 | 
						|
                form.fields["deposit_given"] = forms.BooleanField(
 | 
						|
                    required=True,
 | 
						|
                    disabled=True,
 | 
						|
                    initial=registration.deposit_given,
 | 
						|
                    label=_("Deposit check given"),
 | 
						|
                    help_text=_("Only treasurers can validate this field")
 | 
						|
                )
 | 
						|
            else:
 | 
						|
                form.fields["deposit_given"] = forms.BooleanField(
 | 
						|
                    required=True,
 | 
						|
                    initial=False,
 | 
						|
                    label=_("Create deposit transaction"),
 | 
						|
                    help_text=_("A transaction of %(amount).2f€ will be created from the user's Note account") % {
 | 
						|
                        'amount': registration.wei.deposit_amount / 100
 | 
						|
                    }
 | 
						|
                )
 | 
						|
 | 
						|
        if 'bus' in form.fields:
 | 
						|
            # For 2A+ and hardcoded 1A
 | 
						|
            form.fields["bus"].widget.attrs["api_url"] = "/api/wei/bus/?wei=" + str(registration.wei.pk)
 | 
						|
            if registration.first_year:
 | 
						|
                # Use the results of the survey to fill initial data
 | 
						|
                # A first year has no other role than "1A"
 | 
						|
                del form.fields["roles"]
 | 
						|
                survey = CurrentSurvey(registration)
 | 
						|
                if survey.information.valid:
 | 
						|
                    form.fields["bus"].initial = survey.information.get_selected_bus()
 | 
						|
            else:
 | 
						|
                # Use the choice of the member to fill initial data
 | 
						|
                information = registration.information
 | 
						|
                if "preferred_bus_pk" in information and len(information["preferred_bus_pk"]) == 1:
 | 
						|
                    form["bus"].initial = Bus.objects.get(pk=information["preferred_bus_pk"][0])
 | 
						|
                if "preferred_team_pk" in information and len(information["preferred_team_pk"]) == 1:
 | 
						|
                    form["team"].initial = BusTeam.objects.get(pk=information["preferred_team_pk"][0])
 | 
						|
                if "preferred_roles_pk" in information:
 | 
						|
                    form["roles"].initial = WEIRole.objects.filter(
 | 
						|
                        Q(pk__in=information["preferred_roles_pk"]) | Q(name="Adhérent⋅e WEI")
 | 
						|
                    ).all()
 | 
						|
        return form
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        """
 | 
						|
        Create membership, check that all is good, make transactions
 | 
						|
        """
 | 
						|
        registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
 | 
						|
        club = registration.wei
 | 
						|
        user = registration.user
 | 
						|
 | 
						|
        if "deposit_given" in form.data:
 | 
						|
            registration.deposit_given = form.data["deposit_given"] == "on"
 | 
						|
            registration.save()
 | 
						|
        membership = form.instance
 | 
						|
        membership.user = user
 | 
						|
        membership.club = club
 | 
						|
        membership.date_start = min(date.today(), club.date_start)
 | 
						|
        membership.registration = registration
 | 
						|
        # Force the membership of the clubs BDE and Kfet
 | 
						|
        membership._force_renew_parent = True
 | 
						|
 | 
						|
        fee = club.membership_fee_paid if user.profile.paid else club.membership_fee_unpaid
 | 
						|
        if registration.soge_credit:
 | 
						|
            fee = registration.wei.fee_soge_credit
 | 
						|
 | 
						|
        kfet = club.parent_club
 | 
						|
        bde = kfet.parent_club
 | 
						|
 | 
						|
        kfet_member = Membership.objects.filter(
 | 
						|
            club__name=kfet.name,
 | 
						|
            user=registration.user,
 | 
						|
            date_start__gte=kfet.membership_start,
 | 
						|
        ).exists()
 | 
						|
        bde_member = Membership.objects.filter(
 | 
						|
            club__name=bde.name,
 | 
						|
            user=registration.user,
 | 
						|
            date_start__gte=bde.membership_start,
 | 
						|
        ).exists()
 | 
						|
 | 
						|
        if not kfet_member:
 | 
						|
            fee += kfet.membership_fee_paid if registration.user.profile.paid else kfet.membership_fee_unpaid
 | 
						|
        if not bde_member:
 | 
						|
            fee += bde.membership_fee_paid if registration.user.profile.paid else bde.membership_fee_unpaid
 | 
						|
 | 
						|
        credit_type = form.cleaned_data["credit_type"]
 | 
						|
        credit_amount = form.cleaned_data["credit_amount"]
 | 
						|
        last_name = form.cleaned_data["last_name"]
 | 
						|
        first_name = form.cleaned_data["first_name"]
 | 
						|
        bank = form.cleaned_data["bank"]
 | 
						|
 | 
						|
        if credit_type is None:
 | 
						|
            credit_amount = 0
 | 
						|
 | 
						|
        # Calculer le montant total nécessaire (frais + caution si transaction)
 | 
						|
        total_needed = fee
 | 
						|
        if registration.deposit_type == 'note':
 | 
						|
            total_needed += club.deposit_amount
 | 
						|
 | 
						|
        # Vérifier que l'utilisateur a assez d'argent pour tout payer
 | 
						|
        if user.note.balance + credit_amount < total_needed:
 | 
						|
            form.add_error('credit_type',
 | 
						|
                           _("This user doesn't have enough money to join this club and pay the deposit. "
 | 
						|
                               "Current balance: %(balance)d€, credit: %(credit)d€, needed: %(needed)d€") % {
 | 
						|
                               'balance': user.note.balance,
 | 
						|
                               'credit': credit_amount,
 | 
						|
                               'needed': total_needed}
 | 
						|
                           )
 | 
						|
            return self.form_invalid(form)
 | 
						|
 | 
						|
        if credit_amount:
 | 
						|
            if not last_name:
 | 
						|
                form.add_error('last_name', _("This field is required."))
 | 
						|
                return self.form_invalid(form)
 | 
						|
 | 
						|
            if not first_name:
 | 
						|
                form.add_error('first_name', _("This field is required."))
 | 
						|
                return self.form_invalid(form)
 | 
						|
 | 
						|
            # Credit note before adding the membership
 | 
						|
            SpecialTransaction.objects.create(
 | 
						|
                source=credit_type,
 | 
						|
                destination=registration.user.note,
 | 
						|
                amount=credit_amount,
 | 
						|
                reason="Crédit " + str(credit_type) + " (WEI)",
 | 
						|
                last_name=last_name,
 | 
						|
                first_name=first_name,
 | 
						|
                bank=bank,
 | 
						|
            )
 | 
						|
 | 
						|
        # Now, all is fine, the membership can be created.
 | 
						|
 | 
						|
        if registration.soge_credit:
 | 
						|
            form.instance._soge = True
 | 
						|
 | 
						|
        if registration.first_year:
 | 
						|
            membership = form.instance
 | 
						|
            # If the user is not a member of the club Kfet, then the membership is created.
 | 
						|
            membership.save()
 | 
						|
            membership.refresh_from_db()
 | 
						|
            membership.roles.set(WEIRole.objects.filter(name="1A").all())
 | 
						|
            membership.save()
 | 
						|
 | 
						|
        membership.save()
 | 
						|
        membership.refresh_from_db()
 | 
						|
        membership.roles.add(WEIRole.objects.get(name="Adhérent⋅e WEI"))
 | 
						|
 | 
						|
        # Créer la transaction de caution si nécessaire
 | 
						|
        if registration.deposit_type == 'note':
 | 
						|
            from note.models import Transaction
 | 
						|
            Transaction.objects.create(
 | 
						|
                source=user.note,
 | 
						|
                destination=club.note,
 | 
						|
                quantity=1,
 | 
						|
                amount=club.deposit_amount,
 | 
						|
                reason=_("Deposit %(name)s") % {'name': club.name},
 | 
						|
                valid=True,
 | 
						|
            )
 | 
						|
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def form_invalid(self, form):
 | 
						|
        registration = getattr(form.instance, "registration", None)
 | 
						|
        if registration is not None:
 | 
						|
            registration.deposit_given = False
 | 
						|
            registration.save()
 | 
						|
        return super().form_invalid(form)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:wei_registrations", kwargs={"pk": self.object.club.pk})
 | 
						|
 | 
						|
 | 
						|
class WEIUpdateMembershipView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    """
 | 
						|
    Update a membership for the WEI
 | 
						|
    """
 | 
						|
    model = WEIMembership
 | 
						|
    context_object_name = "membership"
 | 
						|
    template_name = "wei/weimembership_update.html"
 | 
						|
    extra_context = {"title": _("Update WEI Membership")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object().registration.wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a registration once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        # Store the validate parameter in the view's state
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_form(self):
 | 
						|
        form = WEIMembershipForm(
 | 
						|
            self.request.POST or None,
 | 
						|
            self.request.FILES or None,
 | 
						|
            instance=self.object,
 | 
						|
            wei=self.object.registration.wei,
 | 
						|
        )
 | 
						|
 | 
						|
        form.fields["roles"].initial = self.object.roles.all()
 | 
						|
        form.fields["bus"].initial = self.object.bus
 | 
						|
        form.fields["team"].initial = self.object.team
 | 
						|
 | 
						|
        del form.fields["credit_type"]
 | 
						|
        del form.fields["credit_amount"]
 | 
						|
        del form.fields["first_name"]
 | 
						|
        del form.fields["last_name"]
 | 
						|
        del form.fields["bank"]
 | 
						|
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.registration.wei.pk})
 | 
						|
 | 
						|
 | 
						|
class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
 | 
						|
    """
 | 
						|
    Display the survey for the WEI for first year members.
 | 
						|
    Warning: this page is accessible for anyone that is connected, the view doesn't extend ProtectQuerySetMixin.
 | 
						|
    """
 | 
						|
    model = WEIRegistration
 | 
						|
    template_name = "wei/survey.html"
 | 
						|
    survey = None
 | 
						|
    extra_context = {"title": _("Survey WEI")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        obj = self.get_object()
 | 
						|
        self.object = obj
 | 
						|
 | 
						|
        wei = obj.wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't access to the WEI survey once the WEI is started and before the membership start date
 | 
						|
        if today >= wei.date_start or today < wei.membership_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
 | 
						|
        if not self.survey:
 | 
						|
            self.survey = CurrentSurvey(obj)
 | 
						|
 | 
						|
        if request.GET.get("reset") == "true":
 | 
						|
            info = self.survey.information
 | 
						|
            info.reset(obj)
 | 
						|
        # If the survey is complete, then display the end page.
 | 
						|
        if self.survey.is_complete():
 | 
						|
            return redirect(reverse_lazy('wei:wei_survey_end', args=(self.survey.registration.pk,)))
 | 
						|
        # Non first year members don't have a survey
 | 
						|
        if not obj.first_year:
 | 
						|
            return redirect(reverse_lazy('wei:wei_survey_end', args=(self.survey.registration.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_form_class(self):
 | 
						|
        """
 | 
						|
        Get the survey form. It may depend on the current state of the survey.
 | 
						|
        """
 | 
						|
        return self.survey.get_form_class()
 | 
						|
 | 
						|
    def get_form(self, form_class=None):
 | 
						|
        """
 | 
						|
        Update the form with the data of the survey.
 | 
						|
        """
 | 
						|
        form = super().get_form(form_class)
 | 
						|
        self.survey.update_form(form)
 | 
						|
        return form
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
        return context
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def form_valid(self, form):
 | 
						|
        """
 | 
						|
        Update the survey with the data of the form.
 | 
						|
        """
 | 
						|
        self.survey.form_valid(form)
 | 
						|
        return super().form_valid(form)
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        return reverse_lazy('wei:wei_survey', args=(self.get_object().pk,))
 | 
						|
 | 
						|
 | 
						|
class WEISurveyEndView(LoginRequiredMixin, TemplateView):
 | 
						|
    template_name = "wei/survey_end.html"
 | 
						|
    extra_context = {"title": _("Survey WEI")}
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        club = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
 | 
						|
        context["club"] = club
 | 
						|
 | 
						|
        random_user = User.objects.filter(~Q(wei__wei__in=[club])).first()
 | 
						|
 | 
						|
        if random_user is None:
 | 
						|
            # This case occurs when all users are registered to the WEI.
 | 
						|
            # Don't worry, Pikachu never went to the WEI.
 | 
						|
            # This bug can arrive only in dev mode.
 | 
						|
            context["can_add_first_year_member"] = True
 | 
						|
            context["can_add_any_member"] = True
 | 
						|
        else:
 | 
						|
            # Check if the user has the right to create a registration of a random first year member.
 | 
						|
            empty_fy_registration = WEIRegistration(
 | 
						|
                wei=club,
 | 
						|
                user=random_user,
 | 
						|
                first_year=True,
 | 
						|
                birth_date="1970-01-01",
 | 
						|
                gender="No",
 | 
						|
                emergency_contact_name="No",
 | 
						|
                emergency_contact_phone="No",
 | 
						|
            )
 | 
						|
            context["can_add_first_year_member"] = PermissionBackend \
 | 
						|
                .check_perm(self.request, "wei.add_weiregistration", empty_fy_registration)
 | 
						|
 | 
						|
            # Check if the user has the right to create a registration of a random old member.
 | 
						|
            empty_old_registration = WEIRegistration(
 | 
						|
                wei=club,
 | 
						|
                user=User.objects.filter(~Q(wei__wei__in=[club])).first(),
 | 
						|
                first_year=False,
 | 
						|
                birth_date="1970-01-01",
 | 
						|
                gender="No",
 | 
						|
                emergency_contact_name="No",
 | 
						|
                emergency_contact_phone="No",
 | 
						|
            )
 | 
						|
            context["can_add_any_member"] = PermissionBackend \
 | 
						|
                .check_perm(self.request, "wei.add_weiregistration", empty_old_registration)
 | 
						|
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIClosedView(LoginRequiredMixin, TemplateView):
 | 
						|
    template_name = "wei/survey_closed.html"
 | 
						|
    extra_context = {"title": _("Survey WEI")}
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class MemberListRenderView(LoginRequiredMixin, View):
 | 
						|
    """
 | 
						|
    Render Invoice as a generated PDF with the given information and a LaTeX template
 | 
						|
    """
 | 
						|
 | 
						|
    def get_queryset(self, **kwargs):
 | 
						|
        qs = WEIMembership.objects.filter(PermissionBackend.filter_queryset(self.request, WEIMembership, "view"))
 | 
						|
        qs = qs.filter(club__pk=self.kwargs["wei_pk"]).order_by(
 | 
						|
            Lower('bus__name'),
 | 
						|
            Lower('team__name'),
 | 
						|
            'user__profile__promotion',
 | 
						|
            Lower('user__last_name'),
 | 
						|
            Lower('user__first_name'),
 | 
						|
            'id',
 | 
						|
        )
 | 
						|
 | 
						|
        if "bus_pk" in self.kwargs:
 | 
						|
            qs = qs.filter(bus__pk=self.kwargs["bus_pk"])
 | 
						|
 | 
						|
        if "team_pk" in self.kwargs:
 | 
						|
            qs = qs.filter(team__pk=self.kwargs["team_pk"] if self.kwargs["team_pk"] else None)
 | 
						|
 | 
						|
        return qs.distinct()
 | 
						|
 | 
						|
    def get(self, request, **kwargs):
 | 
						|
        qs = self.get_queryset()
 | 
						|
 | 
						|
        wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
 | 
						|
        bus = team = None
 | 
						|
        if "bus_pk" in self.kwargs:
 | 
						|
            bus = Bus.objects.get(pk=self.kwargs["bus_pk"])
 | 
						|
        if "team_pk" in self.kwargs:
 | 
						|
            team = BusTeam.objects.filter(pk=self.kwargs["team_pk"] if self.kwargs["team_pk"] else None)
 | 
						|
            if team.exists():
 | 
						|
                team = team.get()
 | 
						|
                bus = team.bus
 | 
						|
            else:
 | 
						|
                team = dict(name="Staff")
 | 
						|
 | 
						|
        # Fill the template with the information
 | 
						|
        tex = render_to_string("wei/weilist_sample.tex", dict(memberships=qs.all(), wei=wei, bus=bus, team=team))
 | 
						|
 | 
						|
        try:
 | 
						|
            os.mkdir(BASE_DIR + "/tmp")
 | 
						|
        except FileExistsError:
 | 
						|
            pass
 | 
						|
        # We render the file in a temporary directory
 | 
						|
        tmp_dir = mkdtemp(prefix=BASE_DIR + "/tmp/")
 | 
						|
 | 
						|
        try:
 | 
						|
            with open("{}/wei-list.tex".format(tmp_dir), "wb") as f:
 | 
						|
                f.write(tex.encode("UTF-8"))
 | 
						|
            del tex
 | 
						|
 | 
						|
            with open(os.devnull, "wb") as devnull:
 | 
						|
                error = subprocess.Popen(
 | 
						|
                    ["/usr/bin/xelatex", "-interaction=nonstopmode", "{}/wei-list.tex".format(tmp_dir)],
 | 
						|
                    cwd=tmp_dir,
 | 
						|
                    stderr=devnull,
 | 
						|
                    stdout=devnull,
 | 
						|
                ).wait()
 | 
						|
 | 
						|
            if error:
 | 
						|
                with open("{}/wei-list.log".format(tmp_dir), "r") as f:
 | 
						|
                    log = f.read()
 | 
						|
                raise IOError("An error attempted while generating a WEI list (code=" + str(error) + ")\n\n" + log)
 | 
						|
 | 
						|
            # Display the generated pdf as a HTTP Response
 | 
						|
            with open("{}/wei-list.pdf".format(tmp_dir), 'rb') as f:
 | 
						|
                pdf = f.read()
 | 
						|
            response = HttpResponse(pdf, content_type="application/pdf")
 | 
						|
            response['Content-Disposition'] = "inline;filename=Liste%20des%20participants%20au%20WEI.pdf"
 | 
						|
        except IOError as e:
 | 
						|
            raise e
 | 
						|
        finally:
 | 
						|
            # Delete all temporary files
 | 
						|
            shutil.rmtree(tmp_dir)
 | 
						|
 | 
						|
        return response
 | 
						|
 | 
						|
 | 
						|
class WEI1AListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableView):
 | 
						|
    model = WEIRegistration
 | 
						|
    template_name = "wei/1A_list.html"
 | 
						|
    table_class = WEIRegistration1ATable
 | 
						|
    extra_context = {"title": _("Attribute buses to first year members")}
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_queryset(self, filter_permissions=True, **kwargs):
 | 
						|
        qs = super().get_queryset(filter_permissions, **kwargs)
 | 
						|
        qs = qs.filter(first_year=True, membership__isnull=False)
 | 
						|
        qs = qs.filter(wei=self.club)
 | 
						|
        qs = qs.order_by('-membership__bus')
 | 
						|
        return qs
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context['club'] = self.club
 | 
						|
        context['bus_repartition_table'] = BusRepartitionTable(
 | 
						|
            Bus.objects.filter(wei=self.club, size__gt=0)
 | 
						|
                       .filter(PermissionBackend.filter_queryset(self.request, Bus, "view"))
 | 
						|
                       .all())
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIAttributeBus1AView(ProtectQuerysetMixin, DetailView):
 | 
						|
    model = WEIRegistration
 | 
						|
    template_name = "wei/attribute_bus_1A.html"
 | 
						|
    extra_context = {"title": _("Attribute bus")}
 | 
						|
 | 
						|
    def get_queryset(self, filter_permissions=True, **kwargs):
 | 
						|
        qs = super().get_queryset(filter_permissions, **kwargs)
 | 
						|
        qs = qs.filter(first_year=True)
 | 
						|
        return qs
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        obj = self.get_object()
 | 
						|
        if 'selected_bus_pk' not in obj.information:
 | 
						|
            return redirect(reverse_lazy('wei:wei_survey', args=(obj.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context['club'] = self.object.wei
 | 
						|
        context['survey'] = CurrentSurvey(self.object)
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class WEIAttributeBus1ANextView(LoginRequiredMixin, RedirectView):
 | 
						|
    def get_redirect_url(self, *args, **kwargs):
 | 
						|
        wei = WEIClub.objects.filter(pk=self.kwargs['pk'])
 | 
						|
        if not wei.exists():
 | 
						|
            raise Http404
 | 
						|
        wei = wei.get()
 | 
						|
 | 
						|
        # On cherche d'abord les 1A qui ont une inscription validée (membership) mais pas de bus
 | 
						|
        qs = WEIRegistration.objects.filter(
 | 
						|
            wei=wei,
 | 
						|
            first_year=True,
 | 
						|
            membership__isnull=False,
 | 
						|
            membership__bus__isnull=True
 | 
						|
        )
 | 
						|
 | 
						|
        # Parmi eux, on prend ceux qui ont répondu au questionnaire (ont un bus préféré)
 | 
						|
        qs = qs.filter(information_json__contains='selected_bus_pk')
 | 
						|
 | 
						|
        if not qs.exists():
 | 
						|
            # Si on ne trouve personne, on affiche un message et on retourne à la liste
 | 
						|
            messages.info(self.request, _("No first year student without a bus found. Either all of them have a bus, or none has filled the survey yet."))
 | 
						|
            return reverse_lazy('wei:wei_1A_list', args=(wei.pk,))
 | 
						|
 | 
						|
        # On redirige vers la page d'attribution pour le premier étudiant trouvé
 | 
						|
        return reverse_lazy('wei:wei_bus_1A', args=(qs.first().pk,))
 | 
						|
 | 
						|
 | 
						|
class BusInformationUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
						|
    model = Bus
 | 
						|
 | 
						|
    def get_form_class(self):
 | 
						|
        return CurrentSurvey.get_algorithm_class().get_bus_information_form()
 | 
						|
 | 
						|
    def dispatch(self, request, *args, **kwargs):
 | 
						|
        wei = self.get_object().wei
 | 
						|
        today = date.today()
 | 
						|
        # We can't update a bus once the WEI is started
 | 
						|
        if today >= wei.date_start:
 | 
						|
            return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
 | 
						|
        return super().dispatch(request, *args, **kwargs)
 | 
						|
 | 
						|
    def get_context_data(self, **kwargs):
 | 
						|
        context = super().get_context_data(**kwargs)
 | 
						|
        context["club"] = self.object.wei
 | 
						|
        context["information"] = CurrentSurvey.get_algorithm_class().get_bus_information(self.object)
 | 
						|
        self.object.save()
 | 
						|
        return context
 | 
						|
 | 
						|
    def get_success_url(self):
 | 
						|
        self.object.refresh_from_db()
 | 
						|
        return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
 |