from django import forms from django.contrib.auth import get_user_model from django.contrib.auth.forms import AuthenticationForm from django.forms.formsets import BaseFormSet, formset_factory from django.forms.widgets import CheckboxSelectMultiple, RadioSelect from django.utils.translation import gettext_lazy as _ from djconfig.forms import ConfigForm from bda.models import Spectacle from gestioncof.models import CalendarSubscription, Club, CofProfile, EventCommentValue from gestioncof.widgets import TriStateCheckbox User = get_user_model() class ExteAuthenticationForm(AuthenticationForm): """ Formulaire pour l'authentification des extés : renvoie une erreur si la personne qui essaie de s'authentifier n'a pas de mot de passe. L'erreur dépend de si la personne a un login clipper ou non. """ def clean(self): username = self.cleaned_data.get("username") if username is not None: try: user = User.objects.get(username=username) if not user.has_usable_password() or user.password in ("", "!"): profile, created = CofProfile.objects.get_or_create(user=user) if profile.login_clipper: raise forms.ValidationError( _("L'utilisateur·ice a un login clipper !"), code="has_clipper", ) else: raise forms.ValidationError( _("L'utilisateur·ice n'a pas de mot de passe"), code="no_password", ) except User.DoesNotExist: pass return super().clean() class EventForm(forms.Form): def __init__(self, *args, **kwargs): event = kwargs.pop("event") self.event = event current_choices = kwargs.pop("current_choices", None) super().__init__(*args, **kwargs) choices = {} if current_choices: for choice in current_choices.all(): if choice.event_option.id not in choices: choices[choice.event_option.id] = [choice.id] else: choices[choice.event_option.id].append(choice.id) all_choices = choices for option in event.options.all(): choices = [(choice.id, choice.value) for choice in option.choices.all()] if option.multi_choices: initial = [] if option.id not in all_choices else all_choices[option.id] field = forms.MultipleChoiceField( label=option.name, choices=choices, widget=CheckboxSelectMultiple, required=False, initial=initial, ) else: initial = ( None if option.id not in all_choices else all_choices[option.id][0] ) field = forms.ChoiceField( label=option.name, choices=choices, widget=RadioSelect, required=False, initial=initial, ) field.option_id = option.id self.fields["option_%d" % option.id] = field def choices(self): for name, value in self.cleaned_data.items(): if name.startswith("option_"): yield (self.fields[name].option_id, value) class SurveyForm(forms.Form): def __init__(self, *args, **kwargs): survey = kwargs.pop("survey") current_answers = kwargs.pop("current_answers", None) super().__init__(*args, **kwargs) answers = {} if current_answers: for answer in current_answers.all(): if answer.survey_question.id not in answers: answers[answer.survey_question.id] = [answer.id] else: answers[answer.survey_question.id].append(answer.id) for question in survey.questions.all(): choices = [(answer.id, answer.answer) for answer in question.answers.all()] if question.multi_answers: initial = [] if question.id not in answers else answers[question.id] field = forms.MultipleChoiceField( label=question.question, choices=choices, widget=CheckboxSelectMultiple, required=False, initial=initial, ) else: initial = ( None if question.id not in answers else answers[question.id][0] ) field = forms.ChoiceField( label=question.question, choices=choices, widget=RadioSelect, required=False, initial=initial, ) field.question_id = question.id self.fields["question_%d" % question.id] = field def answers(self): for name, value in self.cleaned_data.items(): if name.startswith("question_"): yield (self.fields[name].question_id, value) class SurveyStatusFilterForm(forms.Form): def __init__(self, *args, **kwargs): survey = kwargs.pop("survey") super().__init__(*args, **kwargs) for question in survey.questions.all(): for answer in question.answers.all(): name = "question_%d_answer_%d" % (question.id, answer.id) if self.is_bound and self.data.get(self.add_prefix(name), None): initial = self.data.get(self.add_prefix(name), None) else: initial = "none" field = forms.ChoiceField( label="%s : %s" % (question.question, answer.answer), choices=[("yes", "yes"), ("no", "no"), ("none", "none")], widget=TriStateCheckbox, required=False, initial=initial, ) field.question_id = question.id field.answer_id = answer.id self.fields[name] = field def filters(self): for name, value in self.cleaned_data.items(): if name.startswith("question_"): yield ( self.fields[name].question_id, self.fields[name].answer_id, value, ) class EventStatusFilterForm(forms.Form): def __init__(self, *args, **kwargs): event = kwargs.pop("event") super().__init__(*args, **kwargs) for option in event.options.all(): for choice in option.choices.all(): name = "option_%d_choice_%d" % (option.id, choice.id) if self.is_bound and self.data.get(self.add_prefix(name), None): initial = self.data.get(self.add_prefix(name), None) else: initial = "none" field = forms.ChoiceField( label="%s : %s" % (option.name, choice.value), choices=[("yes", "yes"), ("no", "no"), ("none", "none")], widget=TriStateCheckbox, required=False, initial=initial, ) field.option_id = option.id field.choice_id = choice.id self.fields[name] = field # has_paid name = "event_has_paid" if self.is_bound and self.data.get(self.add_prefix(name), None): initial = self.data.get(self.add_prefix(name), None) else: initial = "none" field = forms.ChoiceField( label="Événement payé", choices=[("yes", "yes"), ("no", "no"), ("none", "none")], widget=TriStateCheckbox, required=False, initial=initial, ) self.fields[name] = field def filters(self): for name, value in self.cleaned_data.items(): if name.startswith("option_"): yield (self.fields[name].option_id, self.fields[name].choice_id, value) elif name == "event_has_paid": yield ("has_paid", None, value) class UserForm(forms.ModelForm): class Meta: model = User fields = ["first_name", "last_name", "email"] class PhoneForm(forms.ModelForm): class Meta: model = CofProfile fields = ["phone"] class ProfileForm(forms.ModelForm): class Meta: model = CofProfile fields = [ "phone", "mailing_cof", "mailing_bda", "mailing_bda_revente", "mailing_unernestaparis", ] class RegistrationUserForm(forms.ModelForm): def __init__(self, *args, **kw): super().__init__(*args, **kw) self.fields["username"].help_text = "" class Meta: model = User fields = ("username", "first_name", "last_name", "email") class RegistrationPassUserForm(RegistrationUserForm): """ Formulaire pour changer le mot de passe d'un utilisateur. """ password1 = forms.CharField(label=_("Mot de passe"), widget=forms.PasswordInput) password2 = forms.CharField( label=_("Confirmation du mot de passe"), widget=forms.PasswordInput ) def clean_password2(self): pass1 = self.cleaned_data["password1"] pass2 = self.cleaned_data["password2"] if pass1 and pass2: if pass1 != pass2: raise forms.ValidationError(_("Mots de passe non identiques.")) return pass2 def save(self, commit=True, *args, **kwargs): user = super().save(commit, *args, **kwargs) user.set_password(self.cleaned_data["password2"]) if commit: user.save() return user class RegistrationProfileForm(forms.ModelForm): def __init__(self, *args, **kw): super().__init__(*args, **kw) self.fields["mailing_cof"].initial = True self.fields["mailing_bda"].initial = True self.fields["mailing_bda_revente"].initial = True self.fields["mailing_unernestaparis"].initial = True class Meta: model = CofProfile fields = [ "login_clipper", "phone", "occupation", "departement", "is_cof", "type_cotiz", "mailing_cof", "mailing_bda", "mailing_bda_revente", "mailing_unernestaparis", "comments", ] STATUS_CHOICES = ( ("no", "Non"), ("wait", "Oui mais attente paiement"), ("paid", "Oui payé"), ) class AdminEventForm(forms.Form): status = forms.ChoiceField( label="Inscription", initial="no", choices=STATUS_CHOICES, widget=RadioSelect ) def __init__(self, *args, **kwargs): self.event = kwargs.pop("event") registration = kwargs.pop("current_registration", None) current_choices, paid = ( (registration.options.all(), registration.paid) if registration is not None else ([], None) ) if paid is True: kwargs["initial"] = {"status": "paid"} elif paid is False: kwargs["initial"] = {"status": "wait"} else: kwargs["initial"] = {"status": "no"} super().__init__(*args, **kwargs) choices = {} for choice in current_choices: if choice.event_option.id not in choices: choices[choice.event_option.id] = [choice.id] else: choices[choice.event_option.id].append(choice.id) all_choices = choices for option in self.event.options.all(): choices = [(choice.id, choice.value) for choice in option.choices.all()] if option.multi_choices: initial = [] if option.id not in all_choices else all_choices[option.id] field = forms.MultipleChoiceField( label=option.name, choices=choices, widget=CheckboxSelectMultiple, required=False, initial=initial, ) else: initial = ( None if option.id not in all_choices else all_choices[option.id][0] ) field = forms.ChoiceField( label=option.name, choices=choices, widget=RadioSelect, required=False, initial=initial, ) field.option_id = option.id self.fields["option_%d" % option.id] = field for commentfield in self.event.commentfields.all(): initial = commentfield.default if registration is not None: try: initial = registration.comments.get( commentfield=commentfield ).content except EventCommentValue.DoesNotExist: pass widget = ( forms.Textarea if commentfield.fieldtype == "text" else forms.TextInput ) field = forms.CharField( label=commentfield.name, widget=widget, required=False, initial=initial ) field.comment_id = commentfield.id self.fields["comment_%d" % commentfield.id] = field def choices(self): for name, value in self.cleaned_data.items(): if name.startswith("option_"): yield (self.fields[name].option_id, value) def comments(self): for name, value in self.cleaned_data.items(): if name.startswith("comment_"): yield (self.fields[name].comment_id, value) class BaseEventRegistrationFormset(BaseFormSet): def __init__(self, *args, **kwargs): self.events = kwargs.pop("events") self.current_registrations = kwargs.pop("current_registrations", None) self.extra = len(self.events) super().__init__(*args, **kwargs) def _construct_form(self, index, **kwargs): kwargs["event"] = self.events[index] if self.current_registrations is not None: kwargs["current_registration"] = self.current_registrations[index] return super()._construct_form(index, **kwargs) EventFormset = formset_factory(AdminEventForm, BaseEventRegistrationFormset) class CalendarForm(forms.ModelForm): subscribe_to_events = forms.BooleanField( initial=True, label="Événements du COF", required=False ) subscribe_to_my_shows = forms.BooleanField( initial=True, label="Les spectacles pour lesquels j'ai obtenu une place", required=False, ) other_shows = forms.ModelMultipleChoiceField( label="Spectacles supplémentaires", queryset=Spectacle.objects.filter(tirage__active=True), widget=forms.CheckboxSelectMultiple, required=False, ) class Meta: model = CalendarSubscription fields = ["subscribe_to_events", "subscribe_to_my_shows", "other_shows"] class ClubsForm(forms.Form): """ Formulaire d'inscription d'un membre à plusieurs clubs du COF. """ clubs = forms.ModelMultipleChoiceField( label="Inscriptions aux clubs du COF", queryset=Club.objects.all(), widget=forms.CheckboxSelectMultiple, required=False, ) # --- # Announcements banner # TODO: move this to the `gestion` app once the supportBDS branch is merged # --- class GestioncofConfigForm(ConfigForm): gestion_banner = forms.CharField( label=_("Announcements banner"), help_text=_("An empty banner disables annoucements"), max_length=2048, required=False, )