mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 09:58:23 +02:00
Improve survey, comment code
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .registration import *
|
||||
from .surveys import *
|
||||
from .registration import WEIForm, WEIRegistrationForm, WEIMembershipForm, BusForm, BusTeamForm
|
||||
from .surveys import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, CurrentSurvey
|
||||
|
||||
__all__ = [
|
||||
'WEIForm', 'WEIRegistrationForm', 'WEIMembershipForm', 'BusForm', 'BusTeamForm',
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget
|
||||
|
||||
from wei.models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole
|
||||
from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole
|
||||
|
||||
|
||||
class WEIForm(forms.ModelForm):
|
||||
@ -25,7 +26,7 @@ class WEIForm(forms.ModelForm):
|
||||
class WEIRegistrationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = WEIRegistration
|
||||
exclude = ('wei', 'information_json', )
|
||||
exclude = ('wei', )
|
||||
widgets = {
|
||||
"user": Autocomplete(
|
||||
User,
|
||||
@ -42,6 +43,12 @@ class WEIRegistrationForm(forms.ModelForm):
|
||||
class WEIMembershipForm(forms.ModelForm):
|
||||
roles = forms.ModelMultipleChoiceField(queryset=WEIRole.objects)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if cleaned_data["team"] is not None and cleaned_data["team"].bus != cleaned_data["bus"]:
|
||||
self.add_error('bus', _("This team doesn't belong to the given team."))
|
||||
return cleaned_data
|
||||
|
||||
class Meta:
|
||||
model = WEIMembership
|
||||
fields = ('roles', 'bus', 'team',)
|
||||
|
@ -1,46 +1,18 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from django.db.models import QuerySet
|
||||
from django.forms import Form
|
||||
|
||||
from ...models import WEIClub, WEIRegistration, Bus
|
||||
|
||||
|
||||
class WEISurvey:
|
||||
year = None
|
||||
step = 0
|
||||
|
||||
def __init__(self, registration):
|
||||
self.registration = registration
|
||||
self.information = self.get_survey_information_class()(registration)
|
||||
|
||||
def get_wei(self):
|
||||
return WEIClub.objects.get(year=self.year)
|
||||
|
||||
def get_survey_information_class(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_form_class(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def update_form(self, form):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_algorithm_class():
|
||||
raise NotImplementedError
|
||||
|
||||
def form_valid(self, form):
|
||||
raise NotImplementedError
|
||||
|
||||
def save(self):
|
||||
self.information.save(self.registration)
|
||||
|
||||
def select_bus(self, bus):
|
||||
self.information.selected_bus_pk = bus.pk
|
||||
self.information.selected_bus_name = bus.name
|
||||
self.information.valid = True
|
||||
|
||||
|
||||
class WEISurveyInformation:
|
||||
"""
|
||||
Abstract data of the survey.
|
||||
"""
|
||||
valid = False
|
||||
selected_bus_pk = None
|
||||
selected_bus_name = None
|
||||
@ -48,22 +20,142 @@ class WEISurveyInformation:
|
||||
def __init__(self, registration):
|
||||
self.__dict__.update(registration.information)
|
||||
|
||||
def get_selected_bus(self):
|
||||
def get_selected_bus(self) -> Optional[Bus]:
|
||||
"""
|
||||
If the algorithm ran, return the prefered bus according to the survey.
|
||||
In the other case, return None.
|
||||
"""
|
||||
if not self.valid:
|
||||
return None
|
||||
return Bus.objects.get(pk=self.selected_bus_pk)
|
||||
|
||||
def save(self, registration):
|
||||
def save(self, registration) -> None:
|
||||
"""
|
||||
Store the data of the survey into the database, with the information of the registration.
|
||||
"""
|
||||
registration.information = self.__dict__
|
||||
registration.save()
|
||||
|
||||
|
||||
class WEISurveyAlgorithm:
|
||||
def get_survey_class(self):
|
||||
"""
|
||||
Abstract algorithm that attributes a bus to each new member.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_survey_class(cls):
|
||||
"""
|
||||
The class of the survey associated with this algorithm.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_registrations(self):
|
||||
return WEIRegistration.objects.filter(wei__year=self.get_survey_class().year, first_year=True).all()
|
||||
@classmethod
|
||||
def get_registrations(cls) -> QuerySet:
|
||||
"""
|
||||
Queryset of all first year registrations
|
||||
"""
|
||||
return WEIRegistration.objects.filter(wei__year=cls.get_survey_class().get_year(), first_year=True)
|
||||
|
||||
def run_algorithm(self):
|
||||
@classmethod
|
||||
def get_buses(cls) -> QuerySet:
|
||||
"""
|
||||
Queryset of all buses of the associated wei.
|
||||
"""
|
||||
return Bus.objects.filter(wei__year=cls.get_survey_class().get_year())
|
||||
|
||||
def run_algorithm(self) -> None:
|
||||
"""
|
||||
Once this method implemented, run the algorithm that attributes a bus to each first year member.
|
||||
This method can be run in command line through ``python manage.py wei_algorithm``
|
||||
See ``wei.management.commmands.wei_algorithm``
|
||||
This method must call Survey.select_bus for each survey.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class WEISurvey:
|
||||
"""
|
||||
Survey associated to a first year WEI registration.
|
||||
The data is stored into WEISurveyInformation, this class acts as a manager.
|
||||
This is an abstract class: this has to be extended each year to implement custom methods.
|
||||
"""
|
||||
|
||||
def __init__(self, registration: WEIRegistration):
|
||||
self.registration = registration
|
||||
self.information = self.get_survey_information_class()(registration)
|
||||
|
||||
@classmethod
|
||||
def get_year(cls) -> int:
|
||||
"""
|
||||
Get year of the wei concerned by the type of the survey.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def get_wei(cls) -> WEIClub:
|
||||
"""
|
||||
The WEI associated to this kind of survey.
|
||||
"""
|
||||
return WEIClub.objects.get(year=cls.get_year())
|
||||
|
||||
@classmethod
|
||||
def get_survey_information_class(cls):
|
||||
"""
|
||||
The class of the data (extending WEISurveyInformation).
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_form_class(self) -> Form:
|
||||
"""
|
||||
The form class of the survey.
|
||||
This is proper to the status of the survey: the form class can evolve according to the progress of the survey.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def update_form(self, form) -> None:
|
||||
"""
|
||||
Once the form is instanciated, the information can be updated with the information of the registration
|
||||
and the information of the survey.
|
||||
This method is called once the form is created.
|
||||
"""
|
||||
pass
|
||||
|
||||
def form_valid(self, form) -> None:
|
||||
"""
|
||||
Called when the information of the form are validated.
|
||||
This method should update the information of the survey.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def is_complete(self) -> bool:
|
||||
"""
|
||||
Return True if the survey is complete.
|
||||
If the survey is complete, then the button "Next" will display some text for the end of the survey.
|
||||
If not, the survey is reloaded and continues.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def save(self) -> None:
|
||||
"""
|
||||
Store the information of the survey into the database.
|
||||
"""
|
||||
self.information.save(self.registration)
|
||||
self.registration.save()
|
||||
|
||||
@classmethod
|
||||
def get_algorithm_class(cls):
|
||||
"""
|
||||
Algorithm class associated to the survey.
|
||||
The algorithm, extending WEISurveyAlgorithm, should associate a bus to each first year member.
|
||||
The association is not permanent: that's only a suggestion.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def select_bus(self, bus) -> None:
|
||||
"""
|
||||
Set the suggestion into the data of the membership.
|
||||
:param bus: The bus suggested.
|
||||
"""
|
||||
self.information.selected_bus_pk = bus.pk
|
||||
self.information.selected_bus_name = bus.name
|
||||
self.information.valid = True
|
||||
|
@ -8,29 +8,50 @@ from ...models import Bus
|
||||
|
||||
|
||||
class WEISurveyForm2020(forms.Form):
|
||||
"""
|
||||
Survey form for the year 2020.
|
||||
For now, that's only a Bus selector.
|
||||
TODO: Do a better survey (later)
|
||||
"""
|
||||
bus = forms.ModelChoiceField(
|
||||
Bus.objects,
|
||||
)
|
||||
|
||||
def set_registration(self, registration):
|
||||
"""
|
||||
Filter the bus selector with the buses of the current WEI.
|
||||
"""
|
||||
self.fields["bus"].queryset = Bus.objects.filter(wei=registration.wei)
|
||||
|
||||
|
||||
class WEISurveyInformation2020(WEISurveyInformation):
|
||||
"""
|
||||
We store the id of the selected bus. We store only the name, but is not used in the selection:
|
||||
that's only for humans that try to read data.
|
||||
"""
|
||||
chosen_bus_pk = None
|
||||
chosen_bus_name = None
|
||||
|
||||
|
||||
class WEISurvey2020(WEISurvey):
|
||||
year = 2020
|
||||
"""
|
||||
Survey for the year 2020.
|
||||
"""
|
||||
@classmethod
|
||||
def get_year(cls):
|
||||
return 2020
|
||||
|
||||
def get_survey_information_class(self):
|
||||
@classmethod
|
||||
def get_survey_information_class(cls):
|
||||
return WEISurveyInformation2020
|
||||
|
||||
def get_form_class(self):
|
||||
return WEISurveyForm2020
|
||||
|
||||
def update_form(self, form):
|
||||
"""
|
||||
Filter the bus selector with the buses of the WEI.
|
||||
"""
|
||||
form.set_registration(self.registration)
|
||||
|
||||
def form_valid(self, form):
|
||||
@ -39,13 +60,26 @@ class WEISurvey2020(WEISurvey):
|
||||
self.information.chosen_bus_name = bus.name
|
||||
self.save()
|
||||
|
||||
@staticmethod
|
||||
def get_algorithm_class():
|
||||
@classmethod
|
||||
def get_algorithm_class(cls):
|
||||
return WEISurveyAlgorithm2020
|
||||
|
||||
def is_complete(self) -> bool:
|
||||
"""
|
||||
The survey is complete once the bus is chosen.
|
||||
"""
|
||||
return self.information.chosen_bus_pk is not None
|
||||
|
||||
|
||||
class WEISurveyAlgorithm2020(WEISurveyAlgorithm):
|
||||
def get_survey_class(self):
|
||||
"""
|
||||
The algorithm class for the year 2020.
|
||||
For now, the algorithm is quite simple: the selected bus is the chosen bus.
|
||||
TODO: Improve this algorithm.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_survey_class(cls):
|
||||
return WEISurvey2020
|
||||
|
||||
def run_algorithm(self):
|
||||
|
Reference in New Issue
Block a user