kpsul/gestioncof/forms.py
2022-10-03 10:55:33 +02:00

446 lines
16 KiB
Python

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,
)