forms.py 21.5 KB
Newer Older
1 2 3
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

4
from django import forms
5
import settings
6

7 8 9
import re
import time
import datetime
10

11 12 13 14
class CreditRetraitWithoutIdbde(Exception):
    """Erreur levée en cas de tentative de crédit ou retrait sans idbde."""
    pass

15
class LoginForm(forms.Form):
16
    """Formulaire de login"""
17
    username = forms.CharField(label="Pseudo")
18
    password = forms.CharField(label="Mot de passe", widget=forms.PasswordInput(render_value=False))
19
    droits = forms.ChoiceField(choices=[(k, settings.ACL_MASKS[k][0]) for k in settings._acl_masks_keys])
20

21
class InviteForm(forms.Form):
22
    """Formulaire d'invitation"""
23 24 25
    nom = forms.CharField(label="Nom")
    prenom = forms.CharField(label="Prénom")

26 27 28
class FrenchFloatField(forms.FloatField):
    """Un champ FloatField, mais qui accepte aussi la virgule comme séparateur"""
    def to_python(self, raw_value):
Vincent Le gallic's avatar
Vincent Le gallic committed
29
        """Conversion de la valeur texte en objet python."""
30
        return super(FrenchFloatField, self).to_python(raw_value.replace(",", "."))
31 32 33 34

class BaseCompteRelatedForm(forms.Form):
    """Classe de base pour tous les formulaires traitant un compte (même une préinscription)"""
    type = forms.ChoiceField(label="Type de compte", choices=[("personne", "Personne"), ("club", "Club")])
Vincent Le gallic's avatar
Vincent Le gallic committed
35 36
    nom = forms.CharField(label="Nom", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    prenom = forms.CharField(label="Prénom", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
37
    sexe = forms.ChoiceField(label="Sexe", choices=[("M", "M"), ("F", "F")])
Vincent Le gallic's avatar
Vincent Le gallic committed
38 39
    mail = forms.CharField(label="E-mail", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    tel = forms.CharField(label="Téléphone", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
40
    adresse = forms.CharField(label="Adresse", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
Vincent Le gallic's avatar
Vincent Le gallic committed
41
    pbsante = forms.CharField(label="Problème de santé", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
42 43
    normalien = forms.BooleanField(label="Normalien", required=False)
    section = forms.CharField(label="Section", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
44 45 46 47


class Regen_pwForm(forms.Form):
    """Formulaire de demande de nouveau mot de passe"""
48 49 50
    nom = forms.CharField(label="Nom", widget=forms.TextInput(attrs={"autocomplete" : "off"}), required=True)
    prenom = forms.CharField(label="Prénom", widget=forms.TextInput(attrs={"autocomplete" : "off"}), required=True)
    mail = forms.CharField(label="E-mail", widget=forms.TextInput(attrs={"autocomplete" : "off"}), required=True)
51 52 53 54 55 56

class CompteRelatedForm(BaseCompteRelatedForm):
    """Classe de base pour les formulaires traitant un compte avec toutes ses données
       (par opposition à une préinscription)."""
    pseudo = forms.CharField(label="Pseudo", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    fonction = forms.CharField(label="Fonction", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
Vincent Le gallic's avatar
Vincent Le gallic committed
57
    commentaire = forms.CharField(label="Commentaire", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
58
    report_period = forms.IntegerField(label="Période des rapports (en minutes)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
59
    bloque = forms.BooleanField(label="Bloquer le compte", required=False)
60 61 62 63
    def __init__(self, *args, **kwargs):
        super(CompteRelatedForm, self).__init__(*args, **kwargs)
        # La section n'est facultative qu'à la préinscription
        self.fields["section"].required = True
Vincent Le gallic's avatar
Vincent Le gallic committed
64
    
65 66
class CompteForm(CompteRelatedForm):
    """Formulaire pour modifier un compte"""
Vincent Le gallic's avatar
Vincent Le gallic committed
67 68
    def clean(self):
        """Supprime les None des champs facultatifs"""
69
        out = super(CompteForm, self).clean()
70
        if out.has_key("report_period") and (out["report_period"] == None):
Vincent Le gallic's avatar
Vincent Le gallic committed
71 72
            del out["report_period"]
        return out
73

74 75 76 77
class PreinscriptionForm(BaseCompteRelatedForm):
    """Formulaire de préinscription"""
    def clean(self):
        """Gestion des None"""
78
        out = super(PreinscriptionForm, self).clean()
79 80
        return out

81 82 83
class ReadhesionForm(forms.Form):
    """Formulaire de réadhésion"""
    wei = forms.BooleanField(label="Inscription au WEI", required=False)
84
    section = forms.CharField(label="Section", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
85
    # partie paiement
86
    on_note = FrenchFloatField(label="Montant supplémentaire à mettre sur la note", required=False, initial=0, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
87
    type_de_paiement = forms.ChoiceField(label="Type de paiement", choices=[("cheque", "Chèque"), ("especes", "Espèces"), ("note", "Débiter sur note"), ("cb", "Carte bancaire"), ("virement", "Virement bancaire"), ("soge", "Société Générale")])
88 89 90 91 92
    pay_nom = forms.CharField(label="Nom¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    pay_prenom = forms.CharField(label="Prénom¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    pay_banque = forms.CharField(label="Banque¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    def clean(self):
        """des valeurs par défaut"""
93
        out = super(ReadhesionForm, self).clean()
94
        if out.has_key("on_note") and type(out["on_note"]) == float:
95
            out["on_note"] = int(round(100 * out["on_note"]))
96 97 98 99 100 101 102
        else:
            out["on_note"] = 0
        if out.has_key("section") and (out["section"] == ""):
            del out["section"]
        return out


103 104 105 106 107
class InscriptionForm(CompteRelatedForm):
    """Formulaire pour inscrire un nouveau compte"""
    wei = forms.BooleanField(label="Inscription au WEI", required=False)
    annee = forms.IntegerField(label="Année d'inscription (année courante si non précisée)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    # partie paiement
108
    on_note = FrenchFloatField(label="Montant supplémentaire à mettre sur la note", required=False, initial=0, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
Charlie Jacomme's avatar
Charlie Jacomme committed
109
    type_de_paiement = forms.ChoiceField(label="Type de paiement", choices=[("cheque", "Chèque"), ("especes", "Espèces"), ("cb", "Carte bancaire"), ("virement", "Virement bancaire"), ("soge", "Société Générale")])
110 111 112 113 114
    pay_nom = forms.CharField(label="Nom¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    pay_prenom = forms.CharField(label="Prénom¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    pay_banque = forms.CharField(label="Banque¹ (pour le paiement)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    def clean(self):
        """des valeurs par défaut"""
115
        out = super(InscriptionForm, self).clean()
116
        if out.has_key("on_note") and type(out["on_note"]) == float:
117
            out["on_note"] = int(round(100 * out["on_note"]))
118 119 120 121 122 123 124 125
        else:
            out["on_note"] = 0
        if out.has_key("report_period") and (out["report_period"] == None):
            del out["report_period"]
        if out.has_key("annee") and (out["annee"] == None):
            del out["annee"]
        return out

126
class AliasForm(forms.Form):
127
    """Formulaire pour ajouter un alias"""
Vincent Le gallic's avatar
Vincent Le gallic committed
128
    alias = forms.CharField(label="Nouvel alias", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
Vincent Le gallic's avatar
Vincent Le gallic committed
129 130

class PasswordForm(forms.Form):
131
    """Formulaire pour changer un mot de passe"""
132 133
    password = forms.CharField(label="Nouveau mot de passe", widget=forms.PasswordInput)
    password_confirm = forms.CharField(label="Confirmation du mot de passe", widget=forms.PasswordInput, required=True)
Vincent Le gallic's avatar
Vincent Le gallic committed
134
    def clean(self):
135
        """Vérifie que le mot de passe et sa confirmation concordent et enlève le deuxième."""
136
        out = super(PasswordForm, self).clean()
Vincent Le gallic's avatar
Vincent Le gallic committed
137 138
        if self.errors:
            return out
139
        if (out["password"] != out["password_confirm"]):
Vincent Le gallic's avatar
Vincent Le gallic committed
140 141 142
            raise forms.ValidationError("Le mot de passe et sa confirmation ne concordent pas.")
        else:
            del out["password_confirm"]
Vincent Le gallic's avatar
Vincent Le gallic committed
143 144
            return out

145
class SearchForm(CompteRelatedForm):
146
    """Formulaire pour faire une recherche avancée"""
147
    # On peut rechercher sur tous les champs d'un compte, plus les alias et les anciens pseudos
Vincent Le gallic's avatar
Vincent Le gallic committed
148 149
    alias = forms.CharField(label="Alias", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    historique = forms.CharField(label="Ancien pseudo (toujours actif)", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
150 151 152 153 154
    def __init__(self, *args, **kwargs):
        super(CompteRelatedForm, self).__init__(*args, **kwargs)
        # La section n'est facultative qu'à la préinscription
	for field in self.fields:
            self.fields[field].required = False
155 156

class SearchHistoriquePseudoForm(forms.Form):
157
    """Formulaire pour faire une recherche par ancien pseudo"""
Vincent Le gallic's avatar
Vincent Le gallic committed
158
    historique = forms.CharField(label="Ancien pseudo", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
159 160
    exactfilter = forms.ChoiceField(label="Correspondance sur :",
                                    widget=forms.RadioSelect,
161
                                    choices=[("b", "début du mot"), ("", "n'importe où dans le mot"), ("x", "correspondance exacte")],
162 163 164 165 166 167 168
                                    required=False)

# Les formats de timestamps acceptés
#  Les dates
### Les %s sont là parce qu'on a besoin de placer les groupes à deux endroits
### dans la regexp, et ça nécessite qu'ils aient deux noms différents
year_match = ur'(?P<y%s>[0-9]{2}|[0-9]{4})'
169
ym1, ym2 = year_match % (1), year_match % (2)
170
month_match = ur'(?P<m%s>[0-9]{1,2})'
171
mm1, mm2 = month_match % (1), month_match % (2)
172
day_match = ur'(?P<d%s>[0-9]{1,2})'
173 174
dm1, dm2 = day_match % (1), day_match % (2)
date_match = ur'^(?:' + ym1 + '-' + mm1 + '-' + dm1 + '|' + dm2 + '/' + mm2 + '(?:/' + ym2 + ')?)$'
175 176 177 178 179 180 181 182

date_matcher = re.compile(date_match)

#  Les heures (il n'est pas nécessaire de les spécifier (défaut à 0 pour chaque champ))
hours_match = ur'(?:(?P<H>[0-9]{1,2}) ?(?:h|heures?)?\.?)?'
minutes_match = ur'(?:(?P<M>[0-9]{1,2}) ?(?:m|min|minutes?)?\.?)?'
seconds_match = ur'(?:(?P<S>[0-9]{1,2}) ?(?:s|sec|secondes?)?\.?)?'
separator_match = u"(?::| )?"
183
time_match = u'^' + separator_match.join([hours_match, minutes_match, seconds_match]) + u'$'
184 185 186 187 188

time_matcher = re.compile(time_match)

def to_string_ignoring_None(obj):
    """Convertit un objet en chaîne de caractères, mais avec None -> '' """
189
    if (obj == None):
190 191 192 193 194 195
        return ""
    else:
        return unicode(obj)

def to_int_ignoring_null(obj):
    """Convertit un objet en entier mais avec None et '' -> 0"""
196
    if obj in [None, '']:
197 198 199 200 201 202 203 204 205
        return 0
    else:
        return int(obj)

class MyDateField(forms.CharField):
    """Un champ personnalisé de détection de date.
       Renvoie un objet datetime.date"""
    description = u"Une date (assez souple sur le format d'entrée)"
    
206
    def to_python(self, raw_value):
Vincent Le gallic's avatar
Vincent Le gallic committed
207
        """Conversion de la valeur texte en objet python."""
208
        raw_value = super(MyDateField, self).to_python(raw_value)
Vincent Le gallic's avatar
Vincent Le gallic committed
209
        if raw_value == u'':
210 211 212 213 214
            raise forms.ValidationError(u"Ce champ est obligatoire")
        result = date_matcher.match(raw_value)
        if result:
            data = result.groupdict()
            # On commence par fusionner ce qui n'a été séparé que par les règles de re.compile
215 216 217
            for field in ["y", "m", "d"]:
                f1, f2 = field + "1", field + "2"
                data[field] = to_string_ignoring_None(data[f1]) + to_string_ignoring_None(data[f2])
218 219 220 221 222
                del data[f1], data[f2]
            # On convertit tout ce beau monde en entier
            for f in data.keys():
                data[f] = to_int_ignoring_null(data[f])
            # Si on n'a pas d'année, on met l'année en cours (plus un si la date se retrouve dans le passé)
223
            if (data["y"] == 0):
224
                today = time.localtime()[:3]
225 226
                if today[1:] > (data["m"], data["d"]):
                    data["y"] = today[0] + 1
227 228 229
                else:
                    data["y"] = today[0]
            # Si la date a été donnée à deux chiffres, il faut la passer à 4
230 231 232
            if data["y"] < 1000:
                if data["y"] > settings.YEAR_1900s_OVER:
                    data["y"] += 1900
233
                else:
234
                    data["y"] += 2000
235 236
            # On le renvoie sous forme de datetime.date
            try:
237
                return datetime.date(data["y"], data["m"], data["d"])
238
            except Exception as exc:
239
                raise forms.ValidationError(u'"%s" ne peut pas être transformé en date : "%s"' % (raw_value, exc))
240 241
            return data
        else:
Vincent Le gallic's avatar
Vincent Le gallic committed
242
            raise forms.ValidationError(u'"%s" ne peut pas être transformé en date (essaye le format JJ/MM/AAAA)' % (raw_value))
243 244 245 246 247 248

class MyTimeField(forms.CharField):
    """Un champ personnalisé de détection d'heure.
       Renvoie un objet datetime.time"""
    description = u"Une heure (assez souple sur le format d'entrée)"
    
249
    def to_python(self, raw_value):
Vincent Le gallic's avatar
Vincent Le gallic committed
250
        """Conversion de la valeur texte en objet python."""
251
        raw_value = super(MyTimeField, self).to_python(raw_value)
252 253 254 255 256 257 258 259
        result = time_matcher.match(raw_value)
        if result:
            data = result.groupdict()
            # On convertit tout ce beau monde en entier
            for f in data.keys():
                data[f] = to_int_ignoring_null(data[f])
            # On le renvoie sous forme de datetime.time
            try:
260
                return datetime.time(data["H"], data["M"], data["S"])
261
            except Exception as exc:
262
                raise forms.ValidationError(u'"%s" ne peut pas être transformé en heure : "%s"' % (raw_value, exc))
263
        else:
Vincent Le gallic's avatar
Vincent Le gallic committed
264
            raise forms.ValidationError(u'"%s" ne peut pas être transformé en heure (essaye le format HH:MM:SS)' % (raw_value))
265 266 267

class ActiviteForm(forms.Form):
    """Formulaire pour créer ou modifer une activité"""
268
    id = forms.IntegerField(required=False, widget=forms.HiddenInput)
Vincent Le gallic's avatar
Vincent Le gallic committed
269 270 271 272 273 274 275 276
    titre = forms.CharField(label="Titre", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    signature = forms.CharField(label="Signature", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    description = forms.CharField(label="Description", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    debut_date = MyDateField(label="Date de début", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    debut_time = MyTimeField(label="Heure de début", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    fin_date = MyDateField(label="Date de fin", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    fin_time = MyTimeField(label="Heure de fin", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    lieu = forms.CharField(label="Lieu", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
277 278
    liste = forms.BooleanField(label="Liste d'invités", required=False)
    listeimprimee = forms.BooleanField(label="Liste imprimée", required=False)
279 280 281
    def clean(self):
        """Récupère les données et fusionne les dates et les heures
           pour finalement donner une chaîne %Y-%m-%d %H:%M:%S"""
282
        out = super(ActiviteForm, self).clean()
283
        # à ce stade, out ne contient pas forcément tous les champs si certains ont été fournis vides
284
        if not set(["debut_date", "debut_time", "fin_date", "fin_time"]).issubset(out.keys()):
285
            return out
286 287
        dd, dt, fd, ft = out["debut_date"], out["debut_time"], out["fin_date"], out["fin_time"]
        debut, fin = datetime.datetime(dd.year, dd.month, dd.day, dt.hour, dt.minute, dt.second), datetime.datetime(fd.year, fd.month, fd.day, ft.hour, ft.minute, ft.second)
288
        if debut>fin:
Vincent Le gallic's avatar
Vincent Le gallic committed
289
            raise forms.ValidationError("La méthode DeLorean_TimeTravel() n'est pas encore implémentée dans la Note Kfet 2015, merci de réessayer plus tard ou bien de te résoudre à faire commencer ton activité avant qu'elle ne soit finie.")
290
        else:
291 292
            del out["debut_date"], out["debut_time"], out["fin_date"], out["fin_time"]
            out["debut"], out["fin"] = debut.strftime("%Y-%m-%d %H:%M:%S"), fin.strftime("%Y-%m-%d %H:%M:%S")
293 294 295
            return out
    
    def __init__(self, *args, **kwargs):
296 297 298 299 300
        """Pour initialiser le formulaire, on doit bidouiller un peu pour avoir
           debut_date, debut_time, fin_date et fin_time dans initial.
           
           Gère aussi les subtilités du champ listeimprimee.
           """
301 302
        if 'initial' in kwargs.keys():
            champs = kwargs['initial'].keys()
303
            for champ_date in ["debut", "fin"]:
304
                if champ_date in champs:
305
                    date = time.strptime(kwargs['initial'][champ_date],"%Y-%m-%d %H:%M:%S")
306
                    # On décompose le timestamp en date/heure
307
                    kwargs['initial'][champ_date + "_date"], kwargs['initial'][champ_date + '_time'] = time.strftime("%d/%m/%Y %H:%M:%S", date).split(" ")
308
                    del kwargs['initial'][champ_date]
309 310 311 312 313 314
        # Il faut aussi faire en sorte que le champ "liste imprimée" ne soit pas toujours disponible
        if 'listeimprimee' in kwargs.keys():
            keeplisteimprimee = kwargs['listeimprimee']
            del kwargs['listeimprimee']
        else:
            keeplisteimprimee = True
315
        forms.Form.__init__(self, *args, **kwargs)
316 317
        if not keeplisteimprimee:
            del self.fields['listeimprimee']
318 319 320

class BoutonForm(forms.Form):
    """Formulaire pour créer ou modifier un bouton"""
Vincent Le gallic's avatar
Vincent Le gallic committed
321 322
    label = forms.CharField(label="Label", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    montant = FrenchFloatField(label="Montant", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
323 324
    destinataire = forms.ChoiceField()
    categorie = forms.ChoiceField()
325
    affiche = forms.BooleanField(label="Afficher", required=False, initial=True)
326
    description = forms.CharField(label="Description", widget=forms.TextInput(attrs={"autocomplete" : "off"}), required=False)
327
    consigne = forms.BooleanField(label="Consigné", required=False, initial=False)
328 329 330 331
    def __init__(self, *args, **kwargs):
        # Pour initialiser le formulaire, on veut que le solde soit passé en euros
        if 'initial' in kwargs.keys():
            if 'montant' in kwargs['initial'].keys():
332
                kwargs['initial']['montant'] = kwargs['initial']['montant'] / 100.0
333 334
        forms.Form.__init__(self, *args, **kwargs)
    def clean(self):
Vincent Le gallic's avatar
Vincent Le gallic committed
335 336
        """Vérifie que le bouton n'est pas absurde :
           montant >= 0, destinataire et montant ``int``."""
337
        out = super(BoutonForm, self).clean()
338
        if out.has_key("montant") and out["montant"] < 0:
339 340 341 342 343 344
            raise forms.ValidationError(u"Le montant d'un bouton doit être positif")
        try:
            out['destinataire'] = int(out['destinataire'])
        except:
            raise forms.ValidationError(u"Je sais pas comme tu t'es débrouillé pour pas me filer un entier dans le champ destinataire, et je veux pas le savoir.")
        try:
345
            out['montant'] = int(round(100 * out['montant']))
346
        except:
Vincent Le gallic's avatar
Vincent Le gallic committed
347
            raise forms.ValidationError(u"Précise un montant correct.")
Vincent Le gallic's avatar
Vincent Le gallic committed
348 349
        return out

350
class PhotoForm(forms.Form):
351
    """Formulaire d'envoi de photo"""
352 353 354
    photo = forms.FileField(label="Fichier photo")
    def clean(self):
        """On n'autorise pas les photos trop grosses."""
355
        out = super(PhotoForm, self).clean()
356 357 358 359
        if out.has_key("photo"):
            photo = out["photo"]
            if photo != None and photo.size > settings.MAX_PHOTO_SIZE:
                raise forms.ValidationError(u"Photo trop volumineuse (%s octets), maximum %s" % (photo.size, settings.MAX_PHOTO_SIZE))
360
        return out
361

362 363
class MoneyForm(forms.Form):
    """Classe de base pour les formulaires qui parlent d'argent."""
Vincent Le gallic's avatar
Vincent Le gallic committed
364
    montant = FrenchFloatField(label="Montant", widget=forms.TextInput(attrs={"autocomplete" : "off"}))
365
    commentaire = forms.CharField(label="Commentaire", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
366
    def clean(self):
Vincent Le gallic's avatar
Vincent Le gallic committed
367
        """Gère les conversions en centimes"""
368
        out = super(MoneyForm, self).clean()
369
        if out.has_key("montant") and type(out["montant"]) == float:
370
            out["montant"] = int(round(100 * out["montant"]))
371 372
        else:
            out["montant"] = 0
373
        return out
374

375 376 377
class CreditRetraitForm(MoneyForm):
    """Formulaire pour effectuer un crédit ou un retrait."""
    idbde = forms.IntegerField(widget=forms.HiddenInput)
378
    type = forms.ChoiceField(label="Type de paiement", choices=[("", "<choisis un mode de paiement>"), ("especes", "Espèces"), ("cb", "Carte bancaire"), ("cheque", "Chèque"), ("virement", "Virement bancaire")])
379 380 381
    nom = forms.CharField(label="Nom", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    prenom = forms.CharField(label="Prénom", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))
    banque = forms.CharField(label="Banque", required=False)
382
    def clean(self):
383
        out = super(CreditRetraitForm, self).clean()
384 385
        if out.get("idbde") is None:
            raise CreditRetraitWithoutIdbde
386
        return out
387 388

class TransfertForm(MoneyForm):
Vincent Le gallic's avatar
Vincent Le gallic committed
389 390
    """Formulaire pour effectuer un transfert d'argent.
       Également utilisé pour les dons."""
391 392
    commentaire = forms.CharField(label="Motif", required=False, widget=forms.TextInput(attrs={"autocomplete" : "off"}))

393 394 395 396

class DeleteCompteForm(forms.Form):
    """Formulaire de confirmation de suppression de compte."""
    anonymiser = forms.BooleanField(label="Anonymiser le compte (nom, prénom, mail, adresse, …)", required=False)