diff --git a/apps/wei/forms/registration.py b/apps/wei/forms/registration.py index 7a7033a7..e934fb50 100644 --- a/apps/wei/forms/registration.py +++ b/apps/wei/forms/registration.py @@ -48,8 +48,7 @@ class WEIRegistrationForm(forms.ModelForm): 'placeholder': 'Nom ...', }, ), - "birth_date": DatePickerInput(options={'defaultDate': '2000-01-01', - 'minDate': '1900-01-01', + "birth_date": DatePickerInput(options={'minDate': '1900-01-01', 'maxDate': '2100-01-01'}), } diff --git a/apps/wei/tables.py b/apps/wei/tables.py index 0f48dcc1..2565bcbc 100644 --- a/apps/wei/tables.py +++ b/apps/wei/tables.py @@ -4,6 +4,7 @@ from datetime import date import django_tables2 as tables +from django.db.models import Q from django.urls import reverse_lazy from django.utils.html import format_html from django.utils.translation import gettext_lazy as _ @@ -169,6 +170,36 @@ class WEIMembershipTable(tables.Table): } +class WEIRegistration1ATable(tables.Table): + user = tables.LinkColumn( + 'wei:wei_update_registration', + args=[A('pk')], + ) + + preferred_bus = tables.Column( + verbose_name=_('preferred bus').capitalize, + accessor='pk', + orderable=False, + ) + + def render_preferred_bus(self, record): + information = record.information + return information['selected_bus_name'] if 'selected_bus_name' in information else "—" + + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + model = WEIMembership + template_name = 'django_tables2/bootstrap4.html' + fields = ('user', 'user__last_name', 'user__first_name', 'gender', + 'user__profile__department', 'preferred_bus', ) + row_attrs = { + 'class': 'table-row', + 'id': lambda record: "row-" + str(record.pk), + } + + class BusTable(tables.Table): name = tables.LinkColumn( 'wei:manage_bus', @@ -245,3 +276,66 @@ class BusTeamTable(tables.Table): 'id': lambda record: "row-" + str(record.pk), 'data-href': lambda record: reverse_lazy('wei:manage_bus_team', args=(record.pk, )) } + + +class BusRepartitionTable(tables.Table): + name = tables.Column( + verbose_name=_("name").capitalize, + accessor='name', + ) + + suggested_first_year = tables.Column( + verbose_name=_("suggested first year").capitalize, + accessor='pk', + orderable=False, + ) + + validated_first_year = tables.Column( + verbose_name=_("validated first year").capitalize, + accessor='pk', + orderable=False, + ) + + validated_staff = tables.Column( + verbose_name=_("validated staff").capitalize, + accessor='pk', + orderable=False, + ) + + size = tables.Column( + verbose_name=_("seat count in the bus").capitalize, + accessor='size', + ) + + free_seats = tables.Column( + verbose_name=_("free seats").capitalize, + accessor='pk', + orderable=False, + ) + + def render_suggested_first_year(self, record): + registrations = WEIRegistration.objects.filter(Q(membership__isnull=True) | Q(membership__bus__isnull=True), + first_year=True, wei=record.wei) + registrations = [r for r in registrations if 'selected_bus_pk' in r.information] + return sum(1 for r in registrations if r.information['selected_bus_pk'] == record.pk) + + def render_validated_first_year(self, record): + return WEIRegistration.objects.filter(first_year=True, membership__bus=record).count() + + def render_validated_staff(self, record): + return WEIRegistration.objects.filter(first_year=False, membership__bus=record).count() + + def render_free_seats(self, record): + return record.size - self.render_validated_staff(record) - self.render_validated_first_year(record) + + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + models = Bus + template_name = 'django_tables2/bootstrap4.html' + fields = ('name', ) + row_attrs = { + 'class': 'table-row', + 'id': lambda record: "row-" + str(record.pk), + } diff --git a/apps/wei/templates/wei/1A_list.html b/apps/wei/templates/wei/1A_list.html new file mode 100644 index 00000000..044db80e --- /dev/null +++ b/apps/wei/templates/wei/1A_list.html @@ -0,0 +1,20 @@ +{% extends "wei/base.html" %} + +{% load i18n %} +{% load render_table from django_tables2 %} + +{% block profile_content %} +
+
+

{% trans "Attribute first year members into buses" %}

+
+ +
+ {% render_table bus_repartition_table %} +
+ {% trans "Start attribution!" %} +
+ {% render_table table %} +
+
+{% endblock %} diff --git a/apps/wei/templates/wei/weiclub_detail.html b/apps/wei/templates/wei/weiclub_detail.html index 40786add..9ffa7374 100644 --- a/apps/wei/templates/wei/weiclub_detail.html +++ b/apps/wei/templates/wei/weiclub_detail.html @@ -94,6 +94,10 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %} + + {% if can_validate_1a or True %} + {% trans "Attribute buses" %} + {% endif %} {% endblock %} {% block extrajavascript %} diff --git a/apps/wei/urls.py b/apps/wei/urls.py index a7e8ca99..e75e3452 100644 --- a/apps/wei/urls.py +++ b/apps/wei/urls.py @@ -3,7 +3,7 @@ from django.urls import path -from .views import CurrentWEIDetailView, WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\ +from .views import CurrentWEIDetailView, WEI1AListView, WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\ WEIRegistrationsView, WEIMembershipsView, MemberListRenderView,\ BusCreateView, BusManageView, BusUpdateView, BusTeamCreateView, BusTeamManageView, BusTeamUpdateView,\ WEIRegister1AView, WEIRegister2AView, WEIUpdateRegistrationView, WEIDeleteRegistrationView,\ @@ -24,6 +24,7 @@ urlpatterns = [ name="wei_memberships_bus_pdf"), path('detail//memberships/pdf///', MemberListRenderView.as_view(), name="wei_memberships_team_pdf"), + path('bus-1A-list//', WEI1AListView.as_view(), name="wei_1A_list"), path('add-bus//', BusCreateView.as_view(), name="add_bus"), path('manage-bus//', BusManageView.as_view(), name="manage_bus"), path('update-bus//', BusUpdateView.as_view(), name="update_bus"), diff --git a/apps/wei/views.py b/apps/wei/views.py index 7fedcf97..baf4dba9 100644 --- a/apps/wei/views.py +++ b/apps/wei/views.py @@ -13,7 +13,6 @@ from django.core.exceptions import PermissionDenied from django.db import transaction from django.db.models import Q, Count from django.db.models.functions.text import Lower -from django.forms import HiddenInput from django.http import HttpResponse from django.shortcuts import redirect from django.template.loader import render_to_string @@ -34,7 +33,8 @@ 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 WEITable, WEIRegistrationTable, BusTable, BusTeamTable, WEIMembershipTable +from .tables import BusRepartitionTable, BusTable, BusTeamTable, WEITable, WEIRegistrationTable, \ + WEIRegistration1ATable, WEIMembershipTable class CurrentWEIDetailView(LoginRequiredMixin, RedirectView): @@ -1160,3 +1160,25 @@ class MemberListRenderView(LoginRequiredMixin, View): 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) + 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).all()) + return context diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index b8d38275..4adb6f95 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-10 22:08+0200\n" +"POT-Creation-Date: 2021-09-11 19:00+0200\n" "PO-Revision-Date: 2020-11-16 20:02+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: French \n" @@ -56,7 +56,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité." #: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301 #: apps/permission/models.py:330 #: apps/registration/templates/registration/future_profile_detail.html:16 -#: apps/wei/models.py:66 apps/wei/models.py:123 +#: apps/wei/models.py:66 apps/wei/models.py:123 apps/wei/tables.py:283 #: apps/wei/templates/wei/base.html:26 #: apps/wei/templates/wei/weimembership_form.html:14 msgid "name" @@ -257,14 +257,14 @@ msgstr "Type" #: apps/activity/tables.py:82 apps/member/forms.py:186 #: apps/registration/forms.py:90 apps/treasury/forms.py:131 -#: apps/wei/forms/registration.py:105 +#: apps/wei/forms/registration.py:104 msgid "Last name" msgstr "Nom de famille" #: apps/activity/tables.py:84 apps/member/forms.py:191 #: apps/note/templates/note/transaction_form.html:134 #: apps/registration/forms.py:95 apps/treasury/forms.py:133 -#: apps/wei/forms/registration.py:110 +#: apps/wei/forms/registration.py:109 msgid "First name" msgstr "Prénom" @@ -461,7 +461,7 @@ msgstr "créer" #: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201 #: apps/permission/models.py:127 apps/treasury/tables.py:38 -#: apps/wei/tables.py:73 +#: apps/wei/tables.py:74 msgid "delete" msgstr "supprimer" @@ -508,7 +508,7 @@ msgstr "rôles" msgid "fee" msgstr "cotisation" -#: apps/member/apps.py:14 apps/wei/tables.py:196 apps/wei/tables.py:227 +#: apps/member/apps.py:14 apps/wei/tables.py:227 apps/wei/tables.py:258 msgid "member" msgstr "adhérent" @@ -554,12 +554,12 @@ msgid "Check this case if the Société Générale paid the inscription." msgstr "Cochez cette case si la Société Générale a payé l'inscription." #: apps/member/forms.py:172 apps/registration/forms.py:77 -#: apps/wei/forms/registration.py:92 +#: apps/wei/forms/registration.py:91 msgid "Credit type" msgstr "Type de rechargement" #: apps/member/forms.py:173 apps/registration/forms.py:78 -#: apps/wei/forms/registration.py:93 +#: apps/wei/forms/registration.py:92 msgid "No credit" msgstr "Pas de rechargement" @@ -568,13 +568,13 @@ msgid "You can credit the note of the user." msgstr "Vous pouvez créditer la note de l'utilisateur avant l'adhésion." #: apps/member/forms.py:179 apps/registration/forms.py:83 -#: apps/wei/forms/registration.py:98 +#: apps/wei/forms/registration.py:97 msgid "Credit amount" msgstr "Montant à créditer" #: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:140 #: apps/registration/forms.py:100 apps/treasury/forms.py:135 -#: apps/wei/forms/registration.py:115 +#: apps/wei/forms/registration.py:114 msgid "Bank" msgstr "Banque" @@ -1188,7 +1188,7 @@ msgstr "Modifier le club" msgid "Add new member to the club" msgstr "Ajouter un nouveau membre au club" -#: apps/member/views.py:642 apps/wei/views.py:952 +#: apps/member/views.py:642 apps/wei/views.py:956 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." @@ -1494,8 +1494,8 @@ msgstr "" "mode de paiement et un utilisateur ou un club" #: apps/note/models/transactions.py:355 apps/note/models/transactions.py:358 -#: apps/note/models/transactions.py:361 apps/wei/views.py:957 -#: apps/wei/views.py:961 +#: apps/note/models/transactions.py:361 apps/wei/views.py:961 +#: apps/wei/views.py:965 msgid "This field is required." msgstr "Ce champ est requis." @@ -1530,7 +1530,7 @@ msgstr "Pas de motif spécifié" #: apps/note/tables.py:169 apps/note/tables.py:203 apps/treasury/tables.py:39 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:30 #: apps/treasury/templates/treasury/sogecredit_detail.html:65 -#: apps/wei/tables.py:74 apps/wei/tables.py:117 +#: apps/wei/tables.py:75 apps/wei/tables.py:118 #: apps/wei/templates/wei/weiregistration_confirm_delete.html:31 #: note_kfet/templates/oauth2_provider/application_confirm_delete.html:18 #: note_kfet/templates/oauth2_provider/application_detail.html:39 @@ -1539,7 +1539,7 @@ msgid "Delete" msgstr "Supprimer" #: apps/note/tables.py:197 apps/note/templates/note/conso_form.html:132 -#: apps/wei/tables.py:48 apps/wei/tables.py:49 +#: apps/wei/tables.py:49 apps/wei/tables.py:50 #: apps/wei/templates/wei/base.html:89 #: apps/wei/templates/wei/bus_detail.html:20 #: apps/wei/templates/wei/busteam_detail.html:20 @@ -2437,7 +2437,7 @@ msgstr "" "demande de crédit." #: apps/treasury/templates/treasury/sogecredit_detail.html:63 -#: apps/wei/tables.py:59 apps/wei/tables.py:101 +#: apps/wei/tables.py:60 apps/wei/tables.py:102 msgid "Validate" msgstr "Valider" @@ -2516,12 +2516,12 @@ msgstr "" "L'utilisateur sélectionné n'est pas validé. Merci de d'abord valider son " "compte." -#: apps/wei/forms/registration.py:60 apps/wei/models.py:118 +#: apps/wei/forms/registration.py:59 apps/wei/models.py:118 #: apps/wei/models.py:315 msgid "bus" msgstr "bus" -#: apps/wei/forms/registration.py:61 +#: apps/wei/forms/registration.py:60 msgid "" "This choice is not definitive. The WEI organizers are free to attribute for " "you a bus and a team, in particular if you are a free eletron." @@ -2530,11 +2530,11 @@ msgstr "" "attribuer un bus et une équipe, en particulier si vous êtes un électron " "libre." -#: apps/wei/forms/registration.py:68 +#: apps/wei/forms/registration.py:67 msgid "Team" msgstr "Équipe" -#: apps/wei/forms/registration.py:70 +#: apps/wei/forms/registration.py:69 msgid "" "Leave this field empty if you won't be in a team (staff, bus chief, free " "electron)" @@ -2542,12 +2542,12 @@ msgstr "" "Laissez ce champ vide si vous ne serez pas dans une équipe (staff, chef de " "bus ou électron libre)" -#: apps/wei/forms/registration.py:76 apps/wei/forms/registration.py:86 +#: apps/wei/forms/registration.py:75 apps/wei/forms/registration.py:85 #: apps/wei/models.py:153 msgid "WEI Roles" msgstr "Rôles au WEI" -#: apps/wei/forms/registration.py:77 +#: apps/wei/forms/registration.py:76 msgid "Select the roles that you are interested in." msgstr "Sélectionnez les rôles qui vous intéressent." @@ -2571,7 +2571,7 @@ msgstr "début" msgid "date end" msgstr "fin" -#: apps/wei/models.py:70 +#: apps/wei/models.py:70 apps/wei/tables.py:306 msgid "seat count in the bus" msgstr "nombre de sièges dans le bus" @@ -2705,11 +2705,11 @@ msgstr "Adhésion au WEI" msgid "WEI memberships" msgstr "Adhésions au WEI" -#: apps/wei/tables.py:104 +#: apps/wei/tables.py:105 msgid "The user does not have enough money." msgstr "L'utilisateur n'a pas assez d'argent." -#: apps/wei/tables.py:107 +#: apps/wei/tables.py:108 msgid "" "The user is in first year. You may validate the credit, the algorithm will " "run later." @@ -2717,27 +2717,55 @@ msgstr "" "L'utilisateur est en première année, vous pouvez valider le crédit, " "l'algorithme tournera plus tard." -#: apps/wei/tables.py:110 +#: apps/wei/tables.py:111 msgid "The user has enough money, you can validate the registration." msgstr "L'utilisateur a assez d'argent, l'inscription est possible." -#: apps/wei/tables.py:142 +#: apps/wei/tables.py:143 msgid "Year" msgstr "Année" -#: apps/wei/tables.py:180 apps/wei/templates/wei/bus_detail.html:32 +#: apps/wei/tables.py:180 apps/wei/templates/wei/weimembership_form.html:102 +msgid "preferred bus" +msgstr "bus préféré" + +#: apps/wei/tables.py:211 apps/wei/templates/wei/bus_detail.html:32 #: apps/wei/templates/wei/busteam_detail.html:50 msgid "Teams" msgstr "Équipes" -#: apps/wei/tables.py:189 apps/wei/tables.py:230 +#: apps/wei/tables.py:220 apps/wei/tables.py:261 msgid "Members count" msgstr "Nombre de membres" -#: apps/wei/tables.py:196 apps/wei/tables.py:227 +#: apps/wei/tables.py:227 apps/wei/tables.py:258 msgid "members" msgstr "adhérents" +#: apps/wei/tables.py:288 +msgid "suggested first year" +msgstr "1A suggérés" + +#: apps/wei/tables.py:294 +msgid "validated first year" +msgstr "1A validés" + +#: apps/wei/tables.py:300 +msgid "validated staff" +msgstr "2A+ validés" + +#: apps/wei/tables.py:311 +msgid "free seats" +msgstr "sièges libres" + +#: apps/wei/templates/wei/1A_list.html:9 +msgid "Attribute first year members into buses" +msgstr "Attribuer les 1A dans les bus" + +#: apps/wei/templates/wei/1A_list.html:15 +msgid "Start attribution!" +msgstr "Démarrer l'attribution !" + #: apps/wei/templates/wei/base.html:44 msgid "WEI fee (paid students)" msgstr "Prix du WEI (élèves)" @@ -2787,8 +2815,8 @@ msgstr "Télécharger au format PDF" #: apps/wei/templates/wei/survey.html:11 #: apps/wei/templates/wei/survey_closed.html:11 -#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1007 -#: apps/wei/views.py:1062 apps/wei/views.py:1072 +#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:1011 +#: apps/wei/views.py:1066 apps/wei/views.py:1076 msgid "Survey WEI" msgstr "Questionnaire WEI" @@ -2829,6 +2857,10 @@ msgstr "Membres du WEI" msgid "Unvalidated registrations" msgstr "Inscriptions non validées" +#: apps/wei/templates/wei/weiclub_detail.html:99 +msgid "Attribute buses" +msgstr "Répartition dans les bus" + #: apps/wei/templates/wei/weiclub_list.html:14 apps/wei/views.py:78 msgid "Create WEI" msgstr "Créer un WEI" @@ -2865,10 +2897,6 @@ msgstr "L'algorithme n'a pas été exécuté." msgid "caution check given" msgstr "chèque de caution donné" -#: apps/wei/templates/wei/weimembership_form.html:102 -msgid "preferred bus" -msgstr "bus préféré" - #: apps/wei/templates/wei/weimembership_form.html:105 msgid "preferred team" msgstr "équipe préférée" @@ -3042,7 +3070,7 @@ msgstr "" msgid "Register old student to the WEI" msgstr "Inscrire un 2A+ au WEI" -#: apps/wei/views.py:622 apps/wei/views.py:713 +#: apps/wei/views.py:622 apps/wei/views.py:704 msgid "You already opened an account in the Société générale." msgstr "Vous avez déjà ouvert un compte auprès de la société générale." @@ -3050,18 +3078,22 @@ msgstr "Vous avez déjà ouvert un compte auprès de la société générale." msgid "Update WEI Registration" msgstr "Modifier l'inscription WEI" -#: apps/wei/views.py:774 +#: apps/wei/views.py:778 msgid "Delete WEI registration" msgstr "Supprimer l'inscription WEI" -#: apps/wei/views.py:785 +#: apps/wei/views.py:789 msgid "You don't have the right to delete this WEI registration." msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI." -#: apps/wei/views.py:803 +#: apps/wei/views.py:807 msgid "Validate WEI registration" msgstr "Valider l'inscription WEI" +#: apps/wei/views.py:1169 +msgid "Attribute buses to first year members" +msgstr "Répartir les 1A dans les bus" + #: note_kfet/settings/base.py:161 msgid "German" msgstr "Allemand"