1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2024-11-26 10:27:07 +00:00
nk20/apps/wei/views.py

1149 lines
45 KiB
Python
Raw Normal View History

# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
2020-04-11 01:37:06 +00:00
# SPDX-License-Identifier: GPL-3.0-or-later
2020-04-23 16:28:16 +00:00
import os
import shutil
import subprocess
2020-08-14 17:04:44 +00:00
from datetime import date, timedelta
2020-04-23 16:28:16 +00:00
from tempfile import mkdtemp
2020-04-11 22:06:20 +00:00
2020-04-11 21:02:12 +00:00
from django.contrib.auth.mixins import LoginRequiredMixin
2020-04-11 22:06:20 +00:00
from django.contrib.auth.models import User
2020-04-21 15:49:06 +00:00
from django.core.exceptions import PermissionDenied
2020-09-11 20:52:16 +00:00
from django.db import transaction
2020-04-23 16:28:16 +00:00
from django.db.models import Q, Count
2020-04-24 12:03:25 +00:00
from django.db.models.functions.text import Lower
from django.forms import HiddenInput
2020-04-23 16:28:16 +00:00
from django.http import HttpResponse
2020-04-19 23:26:53 +00:00
from django.shortcuts import redirect
2020-04-23 16:28:16 +00:00
from django.template.loader import render_to_string
2020-04-12 00:30:48 +00:00
from django.urls import reverse_lazy
2020-04-23 16:28:16 +00:00
from django.views import View
from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView
2020-04-14 02:46:52 +00:00
from django.utils.translation import gettext_lazy as _
2020-04-20 23:06:54 +00:00
from django.views.generic.edit import BaseFormView, DeleteView
2020-04-11 21:02:12 +00:00
from django_tables2 import SingleTableView
2020-04-12 00:43:22 +00:00
from member.models import Membership, Club
from note.models import Transaction, NoteClub, Alias, SpecialTransaction, NoteSpecial
2020-04-11 22:06:20 +00:00
from note.tables import HistoryTable
2020-04-23 16:28:16 +00:00
from note_kfet.settings import BASE_DIR
2020-04-11 22:06:20 +00:00
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
2020-04-11 01:37:06 +00:00
from .forms.registration import WEIChooseBusForm
2020-04-16 22:48:54 +00:00
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
2020-04-19 18:35:49 +00:00
from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMembershipForm, CurrentSurvey
2020-04-13 19:16:52 +00:00
from .tables import WEITable, WEIRegistrationTable, BusTable, BusTeamTable, WEIMembershipTable
2020-04-11 21:02:12 +00:00
2020-04-18 01:55:30 +00:00
class CurrentWEIDetailView(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
2020-04-22 11:28:52 +00:00
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')
2020-04-18 01:27:12 +00:00
2020-04-11 21:02:12 +00:00
class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
List existing WEI
"""
model = WEIClub
table_class = WEITable
2020-04-18 01:27:12 +00:00
ordering = '-year'
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Search WEI")}
2020-04-11 22:06:20 +00:00
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",
2020-07-31 19:24:23 +00:00
year=0,
date_start=date.today(),
date_end=date.today(),
2020-07-31 19:24:23 +00:00
))
return context
2020-04-11 22:06:20 +00:00
class WEICreateView(ProtectQuerysetMixin, ProtectedCreateView):
2020-04-12 00:43:22 +00:00
"""
Create WEI
"""
2020-04-12 00:43:22 +00:00
model = WEIClub
form_class = WEIForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Create WEI")}
2020-04-12 00:43:22 +00:00
def get_sample_object(self):
return WEIClub(
name="",
email="weiclub@example.com",
year=0,
date_start=date.today(),
date_end=date.today(),
)
2020-09-11 20:52:16 +00:00
@transaction.atomic
2020-04-12 00:43:22 +00:00
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})
2020-04-11 22:06:20 +00:00
class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
View WEI information
"""
model = WEIClub
context_object_name = "club"
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("WEI Detail")}
2020-04-11 22:06:20 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
club = context["club"]
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')
2020-04-11 22:06:20 +00:00
history_table = HistoryTable(club_transactions, prefix="history-")
history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1))
context['history_list'] = history_table
2020-04-12 02:29:44 +00:00
club_member = WEIMembership.objects.filter(
2020-04-11 22:06:20 +00:00
club=club,
2020-08-14 17:04:44 +00:00
date_end__gte=date.today(),
).filter(PermissionBackend.filter_queryset(self.request, WEIMembership, "view"))
2020-04-13 19:16:52 +00:00
membership_table = WEIMembershipTable(data=club_member, prefix="membership-")
2020-04-11 22:06:20 +00:00
membership_table.paginate(per_page=20, page=self.request.GET.get('membership-page', 1))
context['member_list'] = membership_table
2020-04-13 19:16:52 +00:00
pre_registrations = WEIRegistration.objects.filter(
PermissionBackend.filter_queryset(self.request, WEIRegistration, "view")).filter(
2020-04-16 22:48:54 +00:00
membership=None,
wei=club
)
2020-04-12 02:29:44 +00:00
pre_registrations_table = WEIRegistrationTable(data=pre_registrations, prefix="pre-registration-")
pre_registrations_table.paginate(per_page=20, page=self.request.GET.get('pre-registration-page', 1))
2020-04-12 02:29:44 +00:00
context['pre_registrations'] = pre_registrations_table
2020-04-18 01:27:12 +00:00
my_registration = WEIRegistration.objects.filter(wei=club, user=self.request.user)
if my_registration.exists():
my_registration = my_registration.get()
else:
my_registration = None
context["my_registration"] = my_registration
buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request, Bus, "view")) \
.filter(wei=self.object).annotate(count=Count("memberships")).order_by("name")
2020-04-13 03:02:16 +00:00
bus_table = BusTable(data=buses, prefix="bus-")
context['buses'] = bus_table
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)
2020-04-18 01:27:12 +00:00
empty_bus = Bus(
wei=club,
name="",
)
context["can_add_bus"] = PermissionBackend.check_perm(self.request, "wei.add_bus", empty_bus)
2020-04-11 22:06:20 +00:00
2020-04-18 01:55:30 +00:00
context["not_first_year"] = WEIMembership.objects.filter(user=self.request.user).exists()
2020-04-11 22:06:20 +00:00
return context
2020-04-12 00:30:48 +00:00
2020-04-21 15:49:06 +00:00
class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
List all WEI memberships
"""
model = WEIMembership
table_class = WEIMembershipTable
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("View members of the WEI")}
2020-04-21 15:49:06 +00:00
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):
2020-07-25 16:26:18 +00:00
qs = super().get_queryset(**kwargs).filter(club=self.club).distinct()
2020-04-21 15:49:06 +00:00
pattern = self.request.GET.get("search", "")
if not pattern:
return qs.none()
qs = qs.filter(
Q(user__first_name__iregex=pattern)
| Q(user__last_name__iregex=pattern)
| Q(user__note__alias__name__iregex="^" + pattern)
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
| Q(bus__name__iregex=pattern)
| Q(team__name__iregex=pattern)
)
return qs
2020-04-21 15:49:06 +00:00
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
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("View registrations to the WEI")}
2020-04-21 15:49:06 +00:00
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):
2020-07-25 16:26:18 +00:00
qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None).distinct()
2020-04-21 15:49:06 +00:00
pattern = self.request.GET.get("search", "")
if pattern:
qs = qs.filter(
Q(user__first_name__iregex=pattern)
| Q(user__last_name__iregex=pattern)
| Q(user__note__alias__name__iregex="^" + pattern)
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
)
2020-04-21 15:49:06 +00:00
return qs
2020-04-21 15:49:06 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = self.club
context["title"] = _("Find WEI Registration")
return context
2020-04-12 00:30:48 +00:00
class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
Update the information of the WEI.
"""
model = WEIClub
context_object_name = "club"
form_class = WEIForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Update the WEI")}
2020-04-12 00:30:48 +00:00
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)
2020-04-12 00:30:48 +00:00
def get_success_url(self):
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk})
2020-04-12 01:31:08 +00:00
class BusCreateView(ProtectQuerysetMixin, ProtectedCreateView):
2020-04-13 03:02:16 +00:00
"""
Create Bus
"""
model = Bus
form_class = BusForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Create new bus")}
2020-04-13 03:02:16 +00:00
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)
2020-04-13 03:02:16 +00:00
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()
2020-04-13 04:01:27 +00:00
return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
class BusUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
Update Bus
"""
model = Bus
form_class = BusForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Update bus")}
2020-04-13 04:01:27 +00:00
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)
2020-04-13 04:01:27 +00:00
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()
2020-04-13 04:01:27 +00:00
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
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Manage bus")}
2020-04-13 04:01:27 +00:00
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")) \
2020-07-25 16:18:53 +00:00
.filter(bus=bus).annotate(count=Count("memberships")).order_by("name")
2020-04-13 19:16:52 +00:00
teams_table = BusTeamTable(data=teams, prefix="team-")
2020-04-13 04:01:27 +00:00
context["teams"] = teams_table
2020-04-13 19:16:52 +00:00
memberships = WEIMembership.objects.filter(PermissionBackend.filter_queryset(
self.request, WEIMembership, "view")).filter(bus=bus)
2020-04-13 19:16:52 +00:00
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
2020-04-13 04:01:27 +00:00
return context
class BusTeamCreateView(ProtectQuerysetMixin, ProtectedCreateView):
2020-04-13 04:01:27 +00:00
"""
Create BusTeam
"""
model = BusTeam
form_class = BusTeamForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Create new team")}
2020-04-13 04:01:27 +00:00
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)
2020-04-13 04:01:27 +00:00
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()
2020-08-10 21:18:40 +00:00
return reverse_lazy("wei:manage_bus_team", kwargs={"pk": self.object.pk})
2020-04-13 03:02:16 +00:00
2020-04-13 19:16:52 +00:00
class BusTeamUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
Update Bus team
"""
model = BusTeam
form_class = BusTeamForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Update team")}
2020-04-13 19:16:52 +00:00
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)
2020-04-13 19:16:52 +00:00
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})
class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
Manage Bus team
"""
model = BusTeam
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Manage WEI team")}
2020-04-13 19:16:52 +00:00
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)
2020-04-13 19:16:52 +00:00
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):
2020-04-12 01:31:08 +00:00
"""
2020-04-17 19:48:50 +00:00
Register a new user to the WEI
2020-04-12 01:31:08 +00:00
"""
model = WEIRegistration
form_class = WEIRegistrationForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Register first year student to the WEI")}
2020-04-12 01:31:08 +00:00
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 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)
2020-04-17 19:48:50 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = _("Register 1A")
2020-04-18 01:27:12 +00:00
context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
if "myself" in self.request.path:
context["form"].fields["user"].disabled = True
2020-04-17 19:48:50 +00:00
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields["user"].initial = self.request.user
del form.fields["first_year"]
del form.fields["caution_check"]
2020-04-19 23:26:53 +00:00
del form.fields["information_json"]
2020-04-17 19:48:50 +00:00
return form
2020-09-11 20:52:16 +00:00
@transaction.atomic
2020-04-17 19:48:50 +00:00
def form_valid(self, form):
form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
form.instance.first_year = True
2020-04-20 23:06:54 +00:00
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."))
2020-04-20 23:06:54 +00:00
return self.form_invalid(form)
2020-04-17 19:48:50 +00:00
return super().form_valid(form)
def get_success_url(self):
self.object.refresh_from_db()
2020-04-19 18:35:49 +00:00
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
2020-04-17 19:48:50 +00:00
class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
2020-04-17 19:48:50 +00:00
"""
Register an old user to the WEI
"""
model = WEIRegistration
form_class = WEIRegistrationForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Register old student to the WEI")}
2020-04-17 19:48:50 +00:00
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 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)
2020-04-17 19:48:50 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = _("Register 2A+")
2020-04-18 01:27:12 +00:00
context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
if "myself" in self.request.path:
context["form"].fields["user"].disabled = True
2020-08-10 21:18:40 +00:00
choose_bus_form = WEIChooseBusForm(self.request.POST if self.request.POST else None)
2020-08-03 11:33:25 +00:00
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
2020-04-17 19:48:50 +00:00
return context
2020-04-12 01:31:08 +00:00
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields["user"].initial = self.request.user
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.")
2020-04-18 01:55:30 +00:00
del form.fields["caution_check"]
2020-04-16 22:48:54 +00:00
del form.fields["first_year"]
2020-04-19 23:26:53 +00:00
del form.fields["information_json"]
2020-04-18 01:55:30 +00:00
2020-04-12 01:31:08 +00:00
return form
2020-09-11 20:52:16 +00:00
@transaction.atomic
2020-04-12 01:31:08 +00:00
def form_valid(self, form):
2020-04-12 02:29:44 +00:00
form.instance.wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
2020-04-16 22:48:54 +00:00
form.instance.first_year = False
2020-04-20 23:06:54 +00:00
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():
2020-04-20 23:06:54 +00:00
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
form.instance.save()
2020-04-12 02:29:44 +00:00
return super().form_valid(form)
2020-04-12 01:31:08 +00:00
def get_success_url(self):
self.object.refresh_from_db()
2020-04-19 18:35:49 +00:00
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
2020-04-12 02:39:57 +00:00
class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
Update a registration for the WEI
"""
model = WEIRegistration
form_class = WEIRegistrationForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Update WEI Registration")}
2020-04-12 02:39:57 +00:00
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,)))
return super().dispatch(request, *args, **kwargs)
2020-04-18 01:27:12 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = self.object.wei
if self.object.is_validated:
2020-08-10 21:18:40 +00:00
membership_form = WEIMembershipForm(instance=self.object.membership,
data=self.request.POST if self.request.POST else None)
for field_name, field in membership_form.fields.items():
if not PermissionBackend.check_perm(
self.request, "wei.change_membership_" + field_name, self.object.membership):
field.widget = HiddenInput()
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"]
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
if not self.object.soge_credit and self.object.user.profile.soge:
form = context["form"]
form.fields["soge_credit"].disabled = True
form.fields["soge_credit"].help_text = _("You already opened an account in the Société générale.")
2020-04-18 01:27:12 +00:00
return context
2020-04-12 02:39:57 +00:00
def get_form(self, form_class=None):
form = super().get_form(form_class)
2020-04-21 15:49:06 +00:00
form.fields["user"].disabled = True
# The auto-json-format may cause issues with the default field remove
if not PermissionBackend.check_perm(self.request, 'wei.change_weiregistration_information_json', self.object):
del form.fields["information_json"]
2020-04-12 02:39:57 +00:00
return form
2020-09-11 20:52:16 +00:00
@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:
2020-04-21 15:49:06 +00:00
membership_form = WEIMembershipForm(self.request.POST, instance=form.instance.membership)
if not membership_form.is_valid():
2020-04-20 23:06:54 +00:00
return self.form_invalid(form)
membership_form.save()
# 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():
2020-04-20 23:06:54 +00:00
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
form.instance.save()
return super().form_valid(form)
2020-04-12 02:39:57 +00:00
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})
if PermissionBackend.check_perm(self.request, "wei.add_weimembership", WEIMembership(
club=self.object.wei,
user=self.object.user,
date_start=date.today(),
date_end=date.today(),
fee=0,
registration=self.object,
)):
return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk})
2020-04-12 02:39:57 +00:00
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
2020-04-14 01:41:26 +00:00
2020-04-20 23:06:54 +00:00
class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
2020-04-21 15:49:06 +00:00
"""
Delete a non-validated WEI registration
"""
2020-04-20 23:06:54 +00:00
model = WEIRegistration
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Delete WEI registration")}
2020-04-20 23:06:54 +00:00
def dispatch(self, request, *args, **kwargs):
2020-04-21 15:49:06 +00:00
object = self.get_object()
wei = object.wei
2020-04-20 23:06:54 +00:00
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,)))
2020-04-21 15:49:06 +00:00
if not PermissionBackend.check_perm(self.request, "wei.delete_weiregistration", object):
2020-04-25 17:29:18 +00:00
raise PermissionDenied(_("You don't have the right to delete this WEI registration."))
2020-04-21 15:49:06 +00:00
2020-04-20 23:06:54 +00:00
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):
2020-04-14 01:41:26 +00:00
"""
Validate WEI Registration
"""
model = WEIMembership
form_class = WEIMembershipForm
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Validate WEI registration")}
2020-04-14 01:41:26 +00:00
def get_sample_object(self):
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
return WEIMembership(
club=registration.wei,
user=registration.user,
date_start=date.today(),
date_end=date.today() + timedelta(days=1),
fee=0,
registration=registration,
)
def dispatch(self, request, *args, **kwargs):
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).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)
2020-04-14 01:41:26 +00:00
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()
2020-04-14 01:41:26 +00:00
context["club"] = registration.wei
kfet = registration.wei.parent_club
bde = kfet.parent_club
2020-04-14 02:46:52 +00:00
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,
2020-04-14 02:46:52 +00:00
user=registration.user,
date_start__gte=bde.membership_start,
2020-04-14 02:46:52 +00:00
).exists()
2020-04-14 01:41:26 +00:00
context["fee"] = registration.fee
form = context["form"]
if registration.soge_credit:
form.fields["credit_amount"].initial = registration.fee
else:
form.fields["credit_amount"].initial = max(0, registration.fee - registration.user.note.balance)
2020-04-14 01:41:26 +00:00
return context
2020-04-16 22:48:54 +00:00
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
if registration.soge_credit:
form.fields["credit_type"].disabled = True
form.fields["credit_type"].initial = NoteSpecial.objects.get(special_type="Virement bancaire")
form.fields["credit_amount"].disabled = True
form.fields["last_name"].disabled = True
form.fields["first_name"].disabled = True
form.fields["bank"].disabled = True
form.fields["bank"].initial = "Société générale"
2020-04-19 23:26:53 +00:00
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"
2020-04-16 22:48:54 +00:00
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:
2020-04-24 12:03:25 +00:00
form["roles"].initial = WEIRole.objects.filter(
Q(pk__in=information["preferred_roles_pk"]) | Q(name="Adhérent WEI")
).all()
2020-04-16 22:48:54 +00:00
return form
2020-09-11 20:52:16 +00:00
@transaction.atomic
2020-04-14 02:46:52 +00:00
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
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
2020-04-14 02:46:52 +00:00
2020-08-11 11:30:44 +00:00
fee = club.membership_fee_paid if user.profile.paid else club.membership_fee_unpaid
2020-04-14 02:46:52 +00:00
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 or registration.soge_credit:
credit_amount = 0
if not registration.soge_credit and user.note.balance + credit_amount < fee:
2020-04-14 02:46:52 +00:00
# Users must have money before registering to the WEI.
form.add_error('bus',
_("This user don't have enough money to join this club, and can't have a negative balance."))
return super().form_invalid(form)
if credit_amount:
if not last_name:
form.add_error('last_name', _("This field is required."))
return super().form_invalid(form)
2020-04-14 02:46:52 +00:00
if not first_name:
form.add_error('first_name', _("This field is required."))
2020-04-14 02:46:52 +00:00
return super().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,
)
2020-04-14 02:46:52 +00:00
# Now, all is fine, the membership can be created.
if registration.soge_credit:
form.instance._soge = True
2020-04-16 22:48:54 +00:00
if registration.first_year:
membership = form.instance
# If the user is not a member of the club Kfet, then the membership is created.
2020-04-16 22:48:54 +00:00
membership.save()
membership.refresh_from_db()
membership.roles.set(WEIRole.objects.filter(name="1A").all())
membership.save()
membership.save()
2020-04-24 12:03:25 +00:00
membership.refresh_from_db()
membership.roles.add(WEIRole.objects.get(name="Adhérent WEI"))
2020-04-24 12:03:25 +00:00
return super().form_valid(form)
2020-04-14 02:46:52 +00:00
2020-04-14 01:41:26 +00:00
def get_success_url(self):
self.object.refresh_from_db()
2020-04-14 02:46:52 +00:00
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.club.pk})
2020-04-19 18:35:49 +00:00
class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView):
2020-04-19 23:26:53 +00:00
"""
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.
2020-04-19 23:26:53 +00:00
"""
2020-04-19 18:35:49 +00:00
model = WEIRegistration
template_name = "wei/survey.html"
survey = None
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Survey WEI")}
2020-04-19 18:35:49 +00:00
def dispatch(self, request, *args, **kwargs):
2020-04-19 23:26:53 +00:00
obj = self.get_object()
2020-08-07 18:11:28 +00:00
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,)))
2020-04-19 23:26:53 +00:00
if not self.survey:
self.survey = CurrentSurvey(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)
2020-04-19 18:35:49 +00:00
def get_form_class(self):
2020-04-19 23:26:53 +00:00
"""
Get the survey form. It may depend on the current state of the survey.
"""
2020-04-19 18:35:49 +00:00
return self.survey.get_form_class()
def get_form(self, form_class=None):
2020-04-19 23:26:53 +00:00
"""
Update the form with the data of the survey.
"""
2020-04-19 18:35:49 +00:00
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
2020-09-11 20:52:16 +00:00
@transaction.atomic
2020-04-19 18:35:49 +00:00
def form_valid(self, form):
2020-04-19 23:26:53 +00:00
"""
Update the survey with the data of the form.
"""
2020-04-19 18:35:49 +00:00
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,))
2020-04-19 23:26:53 +00:00
class WEISurveyEndView(LoginRequiredMixin, TemplateView):
2020-04-19 23:26:53 +00:00
template_name = "wei/survey_end.html"
2020-07-30 15:30:21 +00:00
extra_context = {"title": _("Survey WEI")}
2020-04-19 23:26:53 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
return context
class WEIClosedView(LoginRequiredMixin, TemplateView):
template_name = "wei/survey_closed.html"
2020-07-30 15:30:21 +00:00
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
2020-04-23 16:28:16 +00:00
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"))
2020-04-23 16:28:16 +00:00
qs = qs.filter(club__pk=self.kwargs["wei_pk"]).order_by(
Lower('bus__name'),
Lower('team__name'),
2020-04-24 12:03:25 +00:00
'user__profile__promotion',
2020-04-23 16:28:16 +00:00
Lower('user__last_name'),
Lower('user__first_name'),
2020-04-24 12:03:25 +00:00
'id',
)
2020-04-23 16:28:16 +00:00
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)
2020-04-24 12:03:25 +00:00
return qs.distinct()
2020-04-23 16:28:16 +00:00
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(
2020-09-06 19:19:17 +00:00
["/usr/bin/xelatex", "-interaction=nonstopmode", "{}/wei-list.tex".format(tmp_dir)],
cwd=tmp_dir,
stderr=devnull,
stdout=devnull,
).wait()
2020-04-23 16:28:16 +00:00
if error:
2020-09-05 07:00:16 +00:00
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)
2020-04-23 16:28:16 +00:00
# Display the generated pdf as a HTTP Response
with open("{}/wei-list.pdf".format(tmp_dir), 'rb') as f:
pdf = f.read()
2020-04-23 16:28:16 +00:00
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