From acf7ecc4ae6447fa83a30f715cc7b160543ee006 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Wed, 5 Aug 2020 14:14:51 +0200
Subject: [PATCH] Use phone number validator

---
 apps/member/models.py           |   4 +-
 apps/member/views.py            |  55 ++---
 apps/wei/models.py              |   4 +-
 locale/de/LC_MESSAGES/django.po | 381 +++++++++++++++++---------------
 locale/fr/LC_MESSAGES/django.po | 269 +++++++++++-----------
 note_kfet/settings/base.py      |   5 +
 requirements/base.txt           |   2 +
 7 files changed, 369 insertions(+), 351 deletions(-)

diff --git a/apps/member/models.py b/apps/member/models.py
index 56e4dff8..e5ec1572 100644
--- a/apps/member/models.py
+++ b/apps/member/models.py
@@ -11,10 +11,10 @@ from django.db import models
 from django.db.models import Q
 from django.template import loader
 from django.urls import reverse, reverse_lazy
-from django.utils import timezone
 from django.utils.encoding import force_bytes
 from django.utils.http import urlsafe_base64_encode
 from django.utils.translation import gettext_lazy as _
+from phonenumber_field.modelfields import PhoneNumberField
 
 from permission.models import Role
 from registration.tokens import email_validation_token
@@ -34,7 +34,7 @@ class Profile(models.Model):
         on_delete=models.CASCADE,
     )
 
-    phone_number = models.CharField(
+    phone_number = PhoneNumberField(
         verbose_name=_('phone number'),
         max_length=50,
         blank=True,
diff --git a/apps/member/views.py b/apps/member/views.py
index 9b3cd288..82d2cf32 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -69,7 +69,9 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
         form.fields['email'].required = True
         form.fields['email'].help_text = _("This address must be valid.")
 
-        context['profile_form'] = self.profile_form(instance=context['user_object'].profile)
+        context['profile_form'] = self.profile_form(instance=context['user_object'].profile,
+                                                    data=self.request.POST if self.request.POST else None)
+
         return context
 
     def form_valid(self, form):
@@ -86,30 +88,33 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
             data=self.request.POST,
             instance=self.object.profile,
         )
-        if form.is_valid() and profile_form.is_valid():
-            new_username = form.data['username']
-            alias = Alias.objects.filter(name=new_username)
-            # Si le nouveau pseudo n'est pas un de nos alias,
-            # on supprime éventuellement un alias similaire pour le remplacer
-            if not alias.exists():
-                similar = Alias.objects.filter(
-                    normalized_name=Alias.normalize(new_username))
-                if similar.exists():
-                    similar.delete()
-
-            olduser = User.objects.get(pk=form.instance.pk)
-
-            user = form.save(commit=False)
-            profile = profile_form.save(commit=False)
-            profile.user = user
-            profile.save()
-            user.save()
-
-            if olduser.email != user.email:
-                # If the user changed her/his email, then it is unvalidated and a confirmation link is sent.
-                user.profile.email_confirmed = False
-                user.profile.save()
-                user.profile.send_email_validation_link()
+        profile_form.full_clean()
+        if not profile_form.is_valid():
+            return super().form_invalid(form)
+
+        new_username = form.data['username']
+        alias = Alias.objects.filter(name=new_username)
+        # Si le nouveau pseudo n'est pas un de nos alias,
+        # on supprime éventuellement un alias similaire pour le remplacer
+        if not alias.exists():
+            similar = Alias.objects.filter(
+                normalized_name=Alias.normalize(new_username))
+            if similar.exists():
+                similar.delete()
+
+        olduser = User.objects.get(pk=form.instance.pk)
+
+        user = form.save(commit=False)
+        profile = profile_form.save(commit=False)
+        profile.user = user
+        profile.save()
+        user.save()
+
+        if olduser.email != user.email:
+            # If the user changed her/his email, then it is unvalidated and a confirmation link is sent.
+            user.profile.email_confirmed = False
+            user.profile.save()
+            user.profile.send_email_validation_link()
 
         return super().form_valid(form)
 
diff --git a/apps/wei/models.py b/apps/wei/models.py
index df353338..e500715a 100644
--- a/apps/wei/models.py
+++ b/apps/wei/models.py
@@ -8,6 +8,8 @@ from django.conf import settings
 from django.contrib.auth.models import User
 from django.db import models
 from django.utils.translation import gettext_lazy as _
+from phonenumber_field.modelfields import PhoneNumberField
+
 from member.models import Club, Membership
 from note.models import MembershipTransaction
 from permission.models import Role
@@ -223,7 +225,7 @@ class WEIRegistration(models.Model):
         verbose_name=_("emergency contact name"),
     )
 
-    emergency_contact_phone = models.CharField(
+    emergency_contact_phone = PhoneNumberField(
         max_length=32,
         verbose_name=_("emergency contact phone"),
     )
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index be04465e..c21f5f55 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-03 23:53+0200\n"
+"POT-Creation-Date: 2020-08-05 13:58+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -44,10 +44,10 @@ msgid "You can't invite more than 3 people to this activity."
 msgstr ""
 
 #: apps/activity/models.py:24 apps/activity/models.py:49
-#: apps/member/models.py:158 apps/note/models/notes.py:212
+#: apps/member/models.py:162 apps/note/models/notes.py:212
 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
 #: apps/note/models/transactions.py:268 apps/permission/models.py:339
-#: apps/wei/models.py:65 apps/wei/models.py:117
+#: apps/wei/models.py:67 apps/wei/models.py:119
 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
 #: templates/registration/future_profile_detail.html:16
 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18
@@ -72,7 +72,7 @@ msgstr ""
 
 #: apps/activity/models.py:54 apps/note/models/transactions.py:81
 #: apps/permission/models.py:120 apps/permission/models.py:199
-#: apps/wei/models.py:71 apps/wei/models.py:128
+#: apps/wei/models.py:73 apps/wei/models.py:130
 #: templates/activity/activity_detail.html:16
 msgid "description"
 msgstr ""
@@ -83,9 +83,9 @@ msgstr ""
 msgid "type"
 msgstr ""
 
-#: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:266
+#: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:270
 #: apps/note/models/notes.py:126 apps/treasury/models.py:222
-#: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14
+#: apps/wei/models.py:161 templates/treasury/sogecredit_detail.html:14
 #: templates/wei/survey.html:16
 msgid "user"
 msgstr ""
@@ -188,12 +188,13 @@ msgstr ""
 
 #: apps/activity/tables.py:77 apps/member/forms.py:103
 #: apps/registration/forms.py:70 apps/treasury/forms.py:120
+#: apps/wei/forms/registration.py:95
 msgid "Last name"
 msgstr ""
 
 #: apps/activity/tables.py:79 apps/member/forms.py:108
 #: apps/registration/forms.py:75 apps/treasury/forms.py:122
-#: templates/note/transaction_form.html:129
+#: apps/wei/forms/registration.py:100 templates/note/transaction_form.html:129
 msgid "First name"
 msgstr ""
 
@@ -267,7 +268,7 @@ msgid "edit"
 msgstr ""
 
 #: apps/logs/models.py:63 apps/note/tables.py:137 apps/note/tables.py:165
-#: apps/permission/models.py:137 apps/wei/tables.py:65
+#: apps/permission/models.py:137 apps/wei/tables.py:73
 msgid "delete"
 msgstr ""
 
@@ -291,29 +292,29 @@ msgstr ""
 msgid "changelogs"
 msgstr ""
 
-#: apps/member/admin.py:52 apps/member/models.py:185
+#: apps/member/admin.py:52 apps/member/models.py:189
 #: templates/member/club_info.html:41
 msgid "membership fee (paid students)"
 msgstr ""
 
-#: apps/member/admin.py:53 apps/member/models.py:190
+#: apps/member/admin.py:53 apps/member/models.py:194
 #: templates/member/club_info.html:44
 msgid "membership fee (unpaid students)"
 msgstr ""
 
-#: apps/member/admin.py:67 apps/member/models.py:277
+#: apps/member/admin.py:67 apps/member/models.py:281
 msgid "roles"
 msgstr ""
 
-#: apps/member/admin.py:68 apps/member/models.py:291
+#: apps/member/admin.py:68 apps/member/models.py:295
 msgid "fee"
 msgstr ""
 
-#: apps/member/apps.py:14 apps/wei/tables.py:150 apps/wei/tables.py:181
+#: apps/member/apps.py:14 apps/wei/tables.py:179 apps/wei/tables.py:210
 msgid "member"
 msgstr ""
 
-#: apps/member/forms.py:59 apps/member/views.py:82
+#: apps/member/forms.py:59 apps/member/views.py:84
 #: apps/registration/forms.py:28
 msgid "An alias with a similar name already exists."
 msgstr ""
@@ -327,10 +328,12 @@ msgid "Check this case is the Société Générale paid the inscription."
 msgstr ""
 
 #: apps/member/forms.py:89 apps/registration/forms.py:57
+#: apps/wei/forms/registration.py:82
 msgid "Credit type"
 msgstr ""
 
 #: apps/member/forms.py:90 apps/registration/forms.py:58
+#: apps/wei/forms/registration.py:83
 msgid "No credit"
 msgstr ""
 
@@ -339,11 +342,13 @@ msgid "You can credit the note of the user."
 msgstr ""
 
 #: apps/member/forms.py:96 apps/registration/forms.py:63
+#: apps/wei/forms/registration.py:88
 msgid "Credit amount"
 msgstr ""
 
 #: apps/member/forms.py:113 apps/registration/forms.py:80
-#: apps/treasury/forms.py:124 templates/note/transaction_form.html:135
+#: apps/treasury/forms.py:124 apps/wei/forms/registration.py:105
+#: templates/note/transaction_form.html:135
 msgid "Bank"
 msgstr ""
 
@@ -355,214 +360,214 @@ msgstr ""
 msgid "Roles"
 msgstr ""
 
-#: apps/member/models.py:34
+#: apps/member/models.py:38
 #: templates/registration/future_profile_detail.html:40
 #: templates/wei/weimembership_form.html:48
 msgid "phone number"
 msgstr ""
 
-#: apps/member/models.py:41 templates/member/profile_info.html:29
+#: apps/member/models.py:45 templates/member/profile_info.html:29
 #: templates/registration/future_profile_detail.html:34
 #: templates/wei/weimembership_form.html:42
 msgid "section"
 msgstr ""
 
-#: apps/member/models.py:42
+#: apps/member/models.py:46
 msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 msgstr ""
 
-#: apps/member/models.py:50 templates/wei/weimembership_form.html:36
+#: apps/member/models.py:54 templates/wei/weimembership_form.html:36
 msgid "department"
 msgstr ""
 
-#: apps/member/models.py:52
+#: apps/member/models.py:56
 msgid "Informatics (A0)"
 msgstr ""
 
-#: apps/member/models.py:53
+#: apps/member/models.py:57
 msgid "Mathematics (A1)"
 msgstr ""
 
-#: apps/member/models.py:54
+#: apps/member/models.py:58
 msgid "Physics (A2)"
 msgstr ""
 
-#: apps/member/models.py:55
+#: apps/member/models.py:59
 msgid "Applied physics (A'2)"
 msgstr ""
 
-#: apps/member/models.py:56
+#: apps/member/models.py:60
 msgid "Chemistry (A''2)"
 msgstr ""
 
-#: apps/member/models.py:57
+#: apps/member/models.py:61
 msgid "Biology (A3)"
 msgstr ""
 
-#: apps/member/models.py:58
+#: apps/member/models.py:62
 msgid "SAPHIRE (B1234)"
 msgstr ""
 
-#: apps/member/models.py:59
+#: apps/member/models.py:63
 msgid "Mechanics (B1)"
 msgstr ""
 
-#: apps/member/models.py:60
+#: apps/member/models.py:64
 msgid "Civil engineering (B2)"
 msgstr ""
 
-#: apps/member/models.py:61
+#: apps/member/models.py:65
 msgid "Mechanical engineering (B3)"
 msgstr ""
 
-#: apps/member/models.py:62
+#: apps/member/models.py:66
 msgid "EEA (B4)"
 msgstr ""
 
-#: apps/member/models.py:63
+#: apps/member/models.py:67
 msgid "Design (C)"
 msgstr ""
 
-#: apps/member/models.py:64
+#: apps/member/models.py:68
 msgid "Economy-management (D2)"
 msgstr ""
 
-#: apps/member/models.py:65
+#: apps/member/models.py:69
 msgid "Social sciences (D3)"
 msgstr ""
 
-#: apps/member/models.py:66
+#: apps/member/models.py:70
 msgid "English (E)"
 msgstr ""
 
-#: apps/member/models.py:67
+#: apps/member/models.py:71
 msgid "External (EXT)"
 msgstr ""
 
-#: apps/member/models.py:74
+#: apps/member/models.py:78
 msgid "promotion"
 msgstr ""
 
-#: apps/member/models.py:75
+#: apps/member/models.py:79
 msgid "Year of entry to the school (None if not ENS student)"
 msgstr ""
 
-#: apps/member/models.py:79 templates/member/profile_info.html:32
+#: apps/member/models.py:83 templates/member/profile_info.html:32
 #: templates/registration/future_profile_detail.html:37
 #: templates/wei/weimembership_form.html:45
 msgid "address"
 msgstr ""
 
-#: apps/member/models.py:86
+#: apps/member/models.py:90
 #: templates/registration/future_profile_detail.html:43
 #: templates/wei/weimembership_form.html:51
 msgid "paid"
 msgstr ""
 
-#: apps/member/models.py:87
+#: apps/member/models.py:91
 msgid "Tells if the user receive a salary."
 msgstr ""
 
-#: apps/member/models.py:92
+#: apps/member/models.py:96
 msgid "email confirmed"
 msgstr ""
 
-#: apps/member/models.py:97
+#: apps/member/models.py:101
 msgid "registration valid"
 msgstr ""
 
-#: apps/member/models.py:126 apps/member/models.py:127
+#: apps/member/models.py:130 apps/member/models.py:131
 msgid "user profile"
 msgstr ""
 
-#: apps/member/models.py:134
+#: apps/member/models.py:138
 msgid "Activate your Note Kfet account"
 msgstr ""
 
-#: apps/member/models.py:163 templates/member/club_info.html:57
+#: apps/member/models.py:167 templates/member/club_info.html:57
 #: templates/registration/future_profile_detail.html:22
 #: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24
 msgid "email"
 msgstr ""
 
-#: apps/member/models.py:170
+#: apps/member/models.py:174
 msgid "parent club"
 msgstr ""
 
-#: apps/member/models.py:179
+#: apps/member/models.py:183
 msgid "require memberships"
 msgstr ""
 
-#: apps/member/models.py:180
+#: apps/member/models.py:184
 msgid "Uncheck if this club don't require memberships."
 msgstr ""
 
-#: apps/member/models.py:196 templates/member/club_info.html:33
+#: apps/member/models.py:200 templates/member/club_info.html:33
 msgid "membership duration"
 msgstr ""
 
-#: apps/member/models.py:197
+#: apps/member/models.py:201
 msgid "The longest time (in days) a membership can last (NULL = infinite)."
 msgstr ""
 
-#: apps/member/models.py:204 templates/member/club_info.html:23
+#: apps/member/models.py:208 templates/member/club_info.html:23
 msgid "membership start"
 msgstr ""
 
-#: apps/member/models.py:205
+#: apps/member/models.py:209
 msgid "How long after January 1st the members can renew their membership."
 msgstr ""
 
-#: apps/member/models.py:212 templates/member/club_info.html:28
+#: apps/member/models.py:216 templates/member/club_info.html:28
 msgid "membership end"
 msgstr ""
 
-#: apps/member/models.py:213
+#: apps/member/models.py:217
 msgid ""
 "How long the membership can last after January 1st of the next year after "
 "members can renew their membership."
 msgstr ""
 
-#: apps/member/models.py:247 apps/member/models.py:272
+#: apps/member/models.py:251 apps/member/models.py:276
 #: apps/note/models/notes.py:163
 msgid "club"
 msgstr ""
 
-#: apps/member/models.py:248
+#: apps/member/models.py:252
 msgid "clubs"
 msgstr ""
 
-#: apps/member/models.py:282
+#: apps/member/models.py:286
 msgid "membership starts on"
 msgstr ""
 
-#: apps/member/models.py:286
+#: apps/member/models.py:290
 msgid "membership ends on"
 msgstr ""
 
-#: apps/member/models.py:310 apps/member/views.py:540 apps/wei/views.py:798
-msgid "User is not a member of the parent club"
-msgstr ""
-
-#: apps/member/models.py:317
+#: apps/member/models.py:342
 #, python-brace-format
 msgid "The role {role} does not apply to the club {club}."
 msgstr ""
 
-#: apps/member/models.py:328 apps/member/views.py:549
+#: apps/member/models.py:353 apps/member/views.py:589
 msgid "User is already a member of the club"
 msgstr ""
 
-#: apps/member/models.py:379
+#: apps/member/models.py:400
+msgid "User is not a member of the parent club"
+msgstr ""
+
+#: apps/member/models.py:453
 #, python-brace-format
 msgid "Membership of {user} for the club {club}"
 msgstr ""
 
-#: apps/member/models.py:382
+#: apps/member/models.py:456
 msgid "membership"
 msgstr ""
 
-#: apps/member/models.py:383
+#: apps/member/models.py:457
 msgid "memberships"
 msgstr ""
 
@@ -580,71 +585,71 @@ msgstr ""
 msgid "This address must be valid."
 msgstr ""
 
-#: apps/member/views.py:128
+#: apps/member/views.py:134
 msgid "Profile detail"
 msgstr ""
 
-#: apps/member/views.py:162
+#: apps/member/views.py:168
 msgid "Search user"
 msgstr ""
 
-#: apps/member/views.py:196 apps/member/views.py:382
+#: apps/member/views.py:202 apps/member/views.py:388
 msgid "Note aliases"
 msgstr ""
 
-#: apps/member/views.py:210
+#: apps/member/views.py:216
 msgid "Update note picture"
 msgstr ""
 
-#: apps/member/views.py:268 templates/member/profile_info.html:43
+#: apps/member/views.py:274 templates/member/profile_info.html:43
 msgid "Manage auth token"
 msgstr ""
 
-#: apps/member/views.py:296
+#: apps/member/views.py:302
 msgid "Create new club"
 msgstr ""
 
-#: apps/member/views.py:308
+#: apps/member/views.py:314
 msgid "Search club"
 msgstr ""
 
-#: apps/member/views.py:333
+#: apps/member/views.py:339
 msgid "Club detail"
 msgstr ""
 
-#: apps/member/views.py:399
+#: apps/member/views.py:405
 msgid "Update club"
 msgstr ""
 
-#: apps/member/views.py:433
+#: apps/member/views.py:439
 msgid "Add new member to the club"
 msgstr ""
 
-#: apps/member/views.py:530 apps/wei/views.py:783
+#: apps/member/views.py:580 apps/wei/views.py:862
 msgid ""
 "This user don't have enough money to join this club, and can't have a "
 "negative balance."
 msgstr ""
 
-#: apps/member/views.py:553
+#: apps/member/views.py:593
 msgid "The membership must start after {:%m-%d-%Y}."
 msgstr ""
 
-#: apps/member/views.py:558
+#: apps/member/views.py:598
 msgid "The membership must begin before {:%m-%d-%Y}."
 msgstr ""
 
-#: apps/member/views.py:575 apps/member/views.py:577 apps/member/views.py:579
+#: apps/member/views.py:615 apps/member/views.py:617 apps/member/views.py:619
 #: apps/registration/views.py:290 apps/registration/views.py:292
-#: apps/registration/views.py:294
+#: apps/registration/views.py:294 apps/wei/views.py:867 apps/wei/views.py:871
 msgid "This field is required."
 msgstr ""
 
-#: apps/member/views.py:647
+#: apps/member/views.py:703
 msgid "Manage roles of an user in the club"
 msgstr ""
 
-#: apps/member/views.py:672
+#: apps/member/views.py:728
 msgid "Members of the club"
 msgstr ""
 
@@ -938,13 +943,13 @@ msgstr ""
 msgid "No reason specified"
 msgstr ""
 
-#: apps/note/tables.py:139 apps/note/tables.py:167 apps/wei/tables.py:66
-#: templates/treasury/sogecredit_detail.html:59
+#: apps/note/tables.py:139 apps/note/tables.py:167 apps/wei/tables.py:74
+#: apps/wei/tables.py:100 templates/treasury/sogecredit_detail.html:59
 #: templates/wei/weiregistration_confirm_delete.html:32
 msgid "Delete"
 msgstr ""
 
-#: apps/note/tables.py:162 apps/wei/tables.py:42 apps/wei/tables.py:43
+#: apps/note/tables.py:162 apps/wei/tables.py:46 apps/wei/tables.py:47
 #: templates/member/club_info.html:67 templates/note/conso_form.html:128
 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
@@ -1163,7 +1168,7 @@ msgstr ""
 #: templates/activity/activity_form.html:9
 #: templates/activity/activity_invite.html:8
 #: templates/django_filters/rest_framework/form.html:5
-#: templates/member/add_members.html:14 templates/member/club_form.html:9
+#: templates/member/add_members.html:31 templates/member/club_form.html:9
 #: templates/note/transactiontemplate_form.html:15
 #: templates/treasury/invoice_form.html:46 templates/wei/bus_form.html:13
 #: templates/wei/busteam_form.html:13 templates/wei/weiclub_form.html:15
@@ -1381,348 +1386,348 @@ msgstr ""
 msgid "List of credits from the Société générale"
 msgstr ""
 
-#: apps/treasury/views.py:384
+#: apps/treasury/views.py:379
 msgid "Manage credits from the Société générale"
 msgstr ""
 
-#: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
-#: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:124
+#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51
+#: apps/wei/models.py:62 apps/wei/models.py:168 templates/base.html:124
 msgid "WEI"
 msgstr ""
 
-#: apps/wei/forms/registration.py:48 apps/wei/models.py:112
-#: apps/wei/models.py:297
+#: apps/wei/forms/registration.py:50 apps/wei/models.py:114
+#: apps/wei/models.py:299
 msgid "bus"
 msgstr ""
 
-#: apps/wei/forms/registration.py:49
+#: apps/wei/forms/registration.py:51
 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."
 msgstr ""
 
-#: apps/wei/forms/registration.py:56
+#: apps/wei/forms/registration.py:58
 msgid "Team"
 msgstr ""
 
-#: apps/wei/forms/registration.py:58
+#: apps/wei/forms/registration.py:60
 msgid ""
 "Leave this field empty if you won't be in a team (staff, bus chief, free "
 "electron)"
 msgstr ""
 
-#: apps/wei/forms/registration.py:64 apps/wei/forms/registration.py:74
-#: apps/wei/models.py:147
+#: apps/wei/forms/registration.py:66 apps/wei/forms/registration.py:76
+#: apps/wei/models.py:149
 msgid "WEI Roles"
 msgstr ""
 
-#: apps/wei/forms/registration.py:65
+#: apps/wei/forms/registration.py:67
 msgid "Select the roles that you are interested in."
 msgstr ""
 
-#: apps/wei/forms/registration.py:81
+#: apps/wei/forms/registration.py:112
 msgid "This team doesn't belong to the given bus."
 msgstr ""
 
-#: apps/wei/models.py:23 templates/wei/weiclub_info.html:23
+#: apps/wei/models.py:25 templates/wei/weiclub_info.html:23
 msgid "year"
 msgstr ""
 
-#: apps/wei/models.py:27 templates/wei/weiclub_info.html:17
+#: apps/wei/models.py:29 templates/wei/weiclub_info.html:17
 msgid "date start"
 msgstr ""
 
-#: apps/wei/models.py:31 templates/wei/weiclub_info.html:20
+#: apps/wei/models.py:33 templates/wei/weiclub_info.html:20
 msgid "date end"
 msgstr ""
 
-#: apps/wei/models.py:76
+#: apps/wei/models.py:78
 msgid "survey information"
 msgstr ""
 
-#: apps/wei/models.py:77
+#: apps/wei/models.py:79
 msgid "Information about the survey for new members, encoded in JSON"
 msgstr ""
 
-#: apps/wei/models.py:99
+#: apps/wei/models.py:101
 msgid "Bus"
 msgstr ""
 
-#: apps/wei/models.py:100 templates/wei/weiclub_tables.html:32
+#: apps/wei/models.py:102 templates/wei/weiclub_tables.html:32
 msgid "Buses"
 msgstr ""
 
-#: apps/wei/models.py:121
+#: apps/wei/models.py:123
 msgid "color"
 msgstr ""
 
-#: apps/wei/models.py:122
+#: apps/wei/models.py:124
 msgid "The color of the T-Shirt, stored with its number equivalent"
 msgstr ""
 
-#: apps/wei/models.py:136
+#: apps/wei/models.py:138
 msgid "Bus team"
 msgstr ""
 
-#: apps/wei/models.py:137
+#: apps/wei/models.py:139
 msgid "Bus teams"
 msgstr ""
 
-#: apps/wei/models.py:146
+#: apps/wei/models.py:148
 msgid "WEI Role"
 msgstr ""
 
-#: apps/wei/models.py:171
+#: apps/wei/models.py:173
 msgid "Credit from Société générale"
 msgstr ""
 
-#: apps/wei/models.py:176
+#: apps/wei/models.py:178
 msgid "Caution check given"
 msgstr ""
 
-#: apps/wei/models.py:180 templates/wei/weimembership_form.html:68
+#: apps/wei/models.py:182 templates/wei/weimembership_form.html:68
 msgid "birth date"
 msgstr ""
 
-#: apps/wei/models.py:186 apps/wei/models.py:196
+#: apps/wei/models.py:188 apps/wei/models.py:198
 msgid "Male"
 msgstr ""
 
-#: apps/wei/models.py:187 apps/wei/models.py:197
+#: apps/wei/models.py:189 apps/wei/models.py:199
 msgid "Female"
 msgstr ""
 
-#: apps/wei/models.py:188
+#: apps/wei/models.py:190
 msgid "Non binary"
 msgstr ""
 
-#: apps/wei/models.py:190 templates/wei/weimembership_form.html:59
+#: apps/wei/models.py:192 templates/wei/weimembership_form.html:59
 msgid "gender"
 msgstr ""
 
-#: apps/wei/models.py:199 templates/wei/weimembership_form.html:62
+#: apps/wei/models.py:201 templates/wei/weimembership_form.html:62
 msgid "clothing cut"
 msgstr ""
 
-#: apps/wei/models.py:212 templates/wei/weimembership_form.html:65
+#: apps/wei/models.py:214 templates/wei/weimembership_form.html:65
 msgid "clothing size"
 msgstr ""
 
-#: apps/wei/models.py:218 templates/wei/weimembership_form.html:71
+#: apps/wei/models.py:220 templates/wei/weimembership_form.html:71
 msgid "health issues"
 msgstr ""
 
-#: apps/wei/models.py:223 templates/wei/weimembership_form.html:74
+#: apps/wei/models.py:225 templates/wei/weimembership_form.html:74
 msgid "emergency contact name"
 msgstr ""
 
-#: apps/wei/models.py:228 templates/wei/weimembership_form.html:77
+#: apps/wei/models.py:230 templates/wei/weimembership_form.html:77
 msgid "emergency contact phone"
 msgstr ""
 
-#: apps/wei/models.py:233 templates/wei/weimembership_form.html:80
+#: apps/wei/models.py:235 templates/wei/weimembership_form.html:80
 msgid ""
 "Register on the mailing list to stay informed of the events of the campus (1 "
 "mail/week)"
 msgstr ""
 
-#: apps/wei/models.py:238 templates/wei/weimembership_form.html:83
+#: apps/wei/models.py:240 templates/wei/weimembership_form.html:83
 msgid ""
 "Register on the mailing list to stay informed of the sport events of the "
 "campus (1 mail/week)"
 msgstr ""
 
-#: apps/wei/models.py:243 templates/wei/weimembership_form.html:86
+#: apps/wei/models.py:245 templates/wei/weimembership_form.html:86
 msgid ""
 "Register on the mailing list to stay informed of the art events of the "
 "campus (1 mail/week)"
 msgstr ""
 
-#: apps/wei/models.py:248 templates/wei/weimembership_form.html:56
+#: apps/wei/models.py:250 templates/wei/weimembership_form.html:56
 msgid "first year"
 msgstr ""
 
-#: apps/wei/models.py:249
+#: apps/wei/models.py:251
 msgid "Tells if the user is new in the school."
 msgstr ""
 
-#: apps/wei/models.py:254
+#: apps/wei/models.py:256
 msgid "registration information"
 msgstr ""
 
-#: apps/wei/models.py:255
+#: apps/wei/models.py:257
 msgid ""
 "Information about the registration (buses for old members, survey fot the "
 "new members), encoded in JSON"
 msgstr ""
 
-#: apps/wei/models.py:286
+#: apps/wei/models.py:288
 msgid "WEI User"
 msgstr ""
 
-#: apps/wei/models.py:287
+#: apps/wei/models.py:289
 msgid "WEI Users"
 msgstr ""
 
-#: apps/wei/models.py:307
+#: apps/wei/models.py:309
 msgid "team"
 msgstr ""
 
-#: apps/wei/models.py:317
+#: apps/wei/models.py:319
 msgid "WEI registration"
 msgstr ""
 
-#: apps/wei/models.py:321
+#: apps/wei/models.py:323
 msgid "WEI membership"
 msgstr ""
 
-#: apps/wei/models.py:322
+#: apps/wei/models.py:324
 msgid "WEI memberships"
 msgstr ""
 
-#: apps/wei/tables.py:53 apps/wei/tables.py:54
+#: apps/wei/tables.py:57 apps/wei/tables.py:58 apps/wei/tables.py:95
 #: templates/treasury/sogecredit_detail.html:57
 msgid "Validate"
 msgstr ""
 
-#: apps/wei/tables.py:96
+#: apps/wei/tables.py:125
 msgid "Year"
 msgstr ""
 
-#: apps/wei/tables.py:134 templates/wei/bus_tables.html:26
+#: apps/wei/tables.py:163 templates/wei/bus_tables.html:26
 #: templates/wei/busteam_tables.html:43
 msgid "Teams"
 msgstr ""
 
-#: apps/wei/tables.py:143 apps/wei/tables.py:184
+#: apps/wei/tables.py:172 apps/wei/tables.py:213
 msgid "Members count"
 msgstr ""
 
-#: apps/wei/tables.py:150 apps/wei/tables.py:181
+#: apps/wei/tables.py:179 apps/wei/tables.py:210
 msgid "members"
 msgstr ""
 
-#: apps/wei/views.py:56
+#: apps/wei/views.py:57
 msgid "Search WEI"
 msgstr ""
 
-#: apps/wei/views.py:74 templates/wei/weiclub_list.html:10
+#: apps/wei/views.py:75 templates/wei/weiclub_list.html:10
 msgid "Create WEI"
 msgstr ""
 
-#: apps/wei/views.py:94
+#: apps/wei/views.py:95
 msgid "WEI Detail"
 msgstr ""
 
-#: apps/wei/views.py:189
+#: apps/wei/views.py:190
 msgid "View members of the WEI"
 msgstr ""
 
-#: apps/wei/views.py:217
+#: apps/wei/views.py:218
 msgid "Find WEI Membership"
 msgstr ""
 
-#: apps/wei/views.py:227
+#: apps/wei/views.py:228
 msgid "View registrations to the WEI"
 msgstr ""
 
-#: apps/wei/views.py:251
+#: apps/wei/views.py:252
 msgid "Find WEI Registration"
 msgstr ""
 
-#: apps/wei/views.py:262
+#: apps/wei/views.py:263
 msgid "Update the WEI"
 msgstr ""
 
-#: apps/wei/views.py:283
+#: apps/wei/views.py:284
 msgid "Create new bus"
 msgstr ""
 
-#: apps/wei/views.py:314
+#: apps/wei/views.py:315
 msgid "Update bus"
 msgstr ""
 
-#: apps/wei/views.py:344
+#: apps/wei/views.py:345
 msgid "Manage bus"
 msgstr ""
 
-#: apps/wei/views.py:371
+#: apps/wei/views.py:372
 msgid "Create new team"
 msgstr ""
 
-#: apps/wei/views.py:403
+#: apps/wei/views.py:404
 msgid "Update team"
 msgstr ""
 
-#: apps/wei/views.py:434
+#: apps/wei/views.py:435
 msgid "Manage WEI team"
 msgstr ""
 
-#: apps/wei/views.py:456
+#: apps/wei/views.py:457
 msgid "Register first year student to the WEI"
 msgstr ""
 
-#: apps/wei/views.py:468 templates/wei/weiclub_info.html:62
+#: apps/wei/views.py:469 templates/wei/weiclub_info.html:62
 msgid "Register 1A"
 msgstr ""
 
-#: apps/wei/views.py:489 apps/wei/views.py:560
+#: apps/wei/views.py:490 apps/wei/views.py:561
 msgid "This user is already registered to this WEI."
 msgstr ""
 
-#: apps/wei/views.py:494
+#: apps/wei/views.py:495
 msgid ""
 "This user can't be in her/his first year since he/she has already participed "
 "to a WEI."
 msgstr ""
 
-#: apps/wei/views.py:511
+#: apps/wei/views.py:512
 msgid "Register old student to the WEI"
 msgstr ""
 
-#: apps/wei/views.py:523 templates/wei/weiclub_info.html:65
+#: apps/wei/views.py:524 templates/wei/weiclub_info.html:65
 msgid "Register 2A+"
 msgstr ""
 
-#: apps/wei/views.py:542 apps/wei/views.py:627
+#: apps/wei/views.py:543 apps/wei/views.py:628
 msgid "You already opened an account in the Société générale."
 msgstr ""
 
-#: apps/wei/views.py:590
+#: apps/wei/views.py:591
 msgid "Update WEI Registration"
 msgstr ""
 
-#: apps/wei/views.py:677
+#: apps/wei/views.py:687
 msgid "Delete WEI registration"
 msgstr ""
 
-#: apps/wei/views.py:688
+#: apps/wei/views.py:698
 msgid "You don't have the right to delete this WEI registration."
 msgstr ""
 
-#: apps/wei/views.py:707
+#: apps/wei/views.py:717
 msgid "Validate WEI registration"
 msgstr ""
 
-#: apps/wei/views.py:787
+#: apps/wei/views.py:856
 msgid "This user didn't give her/his caution check."
 msgstr ""
 
-#: apps/wei/views.py:830 apps/wei/views.py:883 apps/wei/views.py:893
+#: apps/wei/views.py:918 apps/wei/views.py:971 apps/wei/views.py:981
 #: templates/wei/survey.html:12 templates/wei/survey_closed.html:12
 #: templates/wei/survey_end.html:12
 msgid "Survey WEI"
 msgstr ""
 
-#: note_kfet/settings/base.py:156
+#: note_kfet/settings/base.py:157
 msgid "German"
 msgstr ""
 
-#: note_kfet/settings/base.py:157
+#: note_kfet/settings/base.py:158
 msgid "English"
 msgstr ""
 
-#: note_kfet/settings/base.py:158
+#: note_kfet/settings/base.py:159
 msgid "French"
 msgstr ""
 
@@ -1866,6 +1871,21 @@ msgstr ""
 msgid "Field filters"
 msgstr ""
 
+#: templates/member/add_members.html:15
+#, python-format
+msgid ""
+"The user is not a member of the club·s %(clubs)s. An additional fee of "
+"%(pretty_fee)s will be charged to renew automatically the membership in this/"
+"these club·s."
+msgstr ""
+
+#: templates/member/add_members.html:20
+#, python-format
+msgid ""
+"This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will be "
+"charged to adhere automatically to this/these club·s."
+msgstr ""
+
 #: templates/member/alias_update.html:5
 msgid "Add alias"
 msgstr ""
@@ -2571,20 +2591,21 @@ msgid ""
 msgstr ""
 
 #: templates/wei/weimembership_form.html:169
-msgid "The note has enough money, the registration is possible."
+#, python-format
+msgid ""
+"The note has enough money (%(pretty_fee)s required), the registration is "
+"possible."
 msgstr ""
 
-#: templates/wei/weimembership_form.html:176
+#: templates/wei/weimembership_form.html:178
 msgid "The user didn't give her/his caution check."
 msgstr ""
 
-#: templates/wei/weimembership_form.html:184
-#, python-format
+#: templates/wei/weimembership_form.html:186
 msgid ""
-"This user is not a member of the Kfet club for the comming year. Please "
-"adhere <a href=\"%(future_user_detail)s\">here if he/she is in her/his first "
-"year</a> or <a href=\"%(club_detail)s\">here if he/she was an old member</a> "
-"before you validate the registration of the WEI."
+"This user is not a member of the Kfet club for the coming year. The "
+"membership will be processed automatically, the WEI registration includes "
+"the membership fee."
 msgstr ""
 
 #: templates/wei/weimembership_list.html:24
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 6875a00d..cd4f17d7 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-04 20:03+0200\n"
+"POT-Creation-Date: 2020-08-05 13:58+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -45,10 +45,10 @@ msgid "You can't invite more than 3 people to this activity."
 msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
 
 #: apps/activity/models.py:24 apps/activity/models.py:49
-#: apps/member/models.py:159 apps/note/models/notes.py:212
+#: apps/member/models.py:162 apps/note/models/notes.py:212
 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
 #: apps/note/models/transactions.py:268 apps/permission/models.py:339
-#: apps/wei/models.py:65 apps/wei/models.py:117
+#: apps/wei/models.py:67 apps/wei/models.py:119
 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
 #: templates/registration/future_profile_detail.html:16
 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18
@@ -73,7 +73,7 @@ msgstr "types d'activité"
 
 #: apps/activity/models.py:54 apps/note/models/transactions.py:81
 #: apps/permission/models.py:120 apps/permission/models.py:199
-#: apps/wei/models.py:71 apps/wei/models.py:128
+#: apps/wei/models.py:73 apps/wei/models.py:130
 #: templates/activity/activity_detail.html:16
 msgid "description"
 msgstr "description"
@@ -84,9 +84,9 @@ msgstr "description"
 msgid "type"
 msgstr "type"
 
-#: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:267
+#: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:270
 #: apps/note/models/notes.py:126 apps/treasury/models.py:222
-#: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14
+#: apps/wei/models.py:161 templates/treasury/sogecredit_detail.html:14
 #: templates/wei/survey.html:16
 msgid "user"
 msgstr "utilisateur"
@@ -293,21 +293,21 @@ msgstr "journal de modification"
 msgid "changelogs"
 msgstr "journaux de modifications"
 
-#: apps/member/admin.py:52 apps/member/models.py:186
+#: apps/member/admin.py:52 apps/member/models.py:189
 #: templates/member/club_info.html:41
 msgid "membership fee (paid students)"
 msgstr "cotisation pour adhérer (normalien élève)"
 
-#: apps/member/admin.py:53 apps/member/models.py:191
+#: apps/member/admin.py:53 apps/member/models.py:194
 #: templates/member/club_info.html:44
 msgid "membership fee (unpaid students)"
 msgstr "cotisation pour adhérer (normalien étudiant)"
 
-#: apps/member/admin.py:67 apps/member/models.py:278
+#: apps/member/admin.py:67 apps/member/models.py:281
 msgid "roles"
 msgstr "rôles"
 
-#: apps/member/admin.py:68 apps/member/models.py:292
+#: apps/member/admin.py:68 apps/member/models.py:295
 msgid "fee"
 msgstr "cotisation"
 
@@ -315,7 +315,7 @@ msgstr "cotisation"
 msgid "member"
 msgstr "adhérent"
 
-#: apps/member/forms.py:59 apps/member/views.py:82
+#: apps/member/forms.py:59 apps/member/views.py:84
 #: apps/registration/forms.py:28
 msgid "An alias with a similar name already exists."
 msgstr "Un alias avec un nom similaire existe déjà."
@@ -361,171 +361,171 @@ msgstr "Utilisateur"
 msgid "Roles"
 msgstr "Rôles"
 
-#: apps/member/models.py:35
+#: apps/member/models.py:38
 #: templates/registration/future_profile_detail.html:40
 #: templates/wei/weimembership_form.html:48
 msgid "phone number"
 msgstr "numéro de téléphone"
 
-#: apps/member/models.py:42 templates/member/profile_info.html:29
+#: apps/member/models.py:45 templates/member/profile_info.html:29
 #: templates/registration/future_profile_detail.html:34
 #: templates/wei/weimembership_form.html:42
 msgid "section"
 msgstr "section"
 
-#: apps/member/models.py:43
+#: apps/member/models.py:46
 msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 
-#: apps/member/models.py:51 templates/wei/weimembership_form.html:36
+#: apps/member/models.py:54 templates/wei/weimembership_form.html:36
 msgid "department"
 msgstr "département"
 
-#: apps/member/models.py:53
+#: apps/member/models.py:56
 msgid "Informatics (A0)"
 msgstr "Informatique (A0)"
 
-#: apps/member/models.py:54
+#: apps/member/models.py:57
 msgid "Mathematics (A1)"
 msgstr "Mathématiques (A1)"
 
-#: apps/member/models.py:55
+#: apps/member/models.py:58
 msgid "Physics (A2)"
 msgstr "Physique (A2)"
 
-#: apps/member/models.py:56
+#: apps/member/models.py:59
 msgid "Applied physics (A'2)"
 msgstr "Physique appliquée (A'2)"
 
-#: apps/member/models.py:57
+#: apps/member/models.py:60
 msgid "Chemistry (A''2)"
 msgstr "Chimie (A''2)"
 
-#: apps/member/models.py:58
+#: apps/member/models.py:61
 msgid "Biology (A3)"
 msgstr "Biologie (A3)"
 
-#: apps/member/models.py:59
+#: apps/member/models.py:62
 msgid "SAPHIRE (B1234)"
 msgstr "SAPHIRE (B1234)"
 
-#: apps/member/models.py:60
+#: apps/member/models.py:63
 msgid "Mechanics (B1)"
 msgstr "Mécanique (B1)"
 
-#: apps/member/models.py:61
+#: apps/member/models.py:64
 msgid "Civil engineering (B2)"
 msgstr "Génie civil (B2)"
 
-#: apps/member/models.py:62
+#: apps/member/models.py:65
 msgid "Mechanical engineering (B3)"
 msgstr "Génie mécanique (B3)"
 
-#: apps/member/models.py:63
+#: apps/member/models.py:66
 msgid "EEA (B4)"
 msgstr "EEA (B4)"
 
-#: apps/member/models.py:64
+#: apps/member/models.py:67
 msgid "Design (C)"
 msgstr "Design (C)"
 
-#: apps/member/models.py:65
+#: apps/member/models.py:68
 msgid "Economy-management (D2)"
 msgstr "Économie-gestion (D2)"
 
-#: apps/member/models.py:66
+#: apps/member/models.py:69
 msgid "Social sciences (D3)"
 msgstr "Sciences sociales (D3)"
 
-#: apps/member/models.py:67
+#: apps/member/models.py:70
 msgid "English (E)"
 msgstr "Anglais (E)"
 
-#: apps/member/models.py:68
+#: apps/member/models.py:71
 msgid "External (EXT)"
 msgstr "Externe (EXT)"
 
-#: apps/member/models.py:75
+#: apps/member/models.py:78
 msgid "promotion"
 msgstr "promotion"
 
-#: apps/member/models.py:76
+#: apps/member/models.py:79
 msgid "Year of entry to the school (None if not ENS student)"
 msgstr "Année d'entrée dans l'école (None si non-étudiant·e de l'ENS)"
 
-#: apps/member/models.py:80 templates/member/profile_info.html:32
+#: apps/member/models.py:83 templates/member/profile_info.html:32
 #: templates/registration/future_profile_detail.html:37
 #: templates/wei/weimembership_form.html:45
 msgid "address"
 msgstr "adresse"
 
-#: apps/member/models.py:87
+#: apps/member/models.py:90
 #: templates/registration/future_profile_detail.html:43
 #: templates/wei/weimembership_form.html:51
 msgid "paid"
 msgstr "payé"
 
-#: apps/member/models.py:88
+#: apps/member/models.py:91
 msgid "Tells if the user receive a salary."
 msgstr "Indique si l'utilisateur perçoit un salaire."
 
-#: apps/member/models.py:93
+#: apps/member/models.py:96
 msgid "email confirmed"
 msgstr "adresse email confirmée"
 
-#: apps/member/models.py:98
+#: apps/member/models.py:101
 msgid "registration valid"
 msgstr "inscription valid"
 
-#: apps/member/models.py:127 apps/member/models.py:128
+#: apps/member/models.py:130 apps/member/models.py:131
 msgid "user profile"
 msgstr "profil utilisateur"
 
-#: apps/member/models.py:135
+#: apps/member/models.py:138
 msgid "Activate your Note Kfet account"
 msgstr "Activez votre compte Note Kfet"
 
-#: apps/member/models.py:164 templates/member/club_info.html:57
+#: apps/member/models.py:167 templates/member/club_info.html:57
 #: templates/registration/future_profile_detail.html:22
 #: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24
 msgid "email"
 msgstr "courriel"
 
-#: apps/member/models.py:171
+#: apps/member/models.py:174
 msgid "parent club"
 msgstr "club parent"
 
-#: apps/member/models.py:180
+#: apps/member/models.py:183
 msgid "require memberships"
 msgstr "nécessite des adhésions"
 
-#: apps/member/models.py:181
+#: apps/member/models.py:184
 msgid "Uncheck if this club don't require memberships."
 msgstr "Décochez si ce club n'utilise pas d'adhésions."
 
-#: apps/member/models.py:197 templates/member/club_info.html:33
+#: apps/member/models.py:200 templates/member/club_info.html:33
 msgid "membership duration"
 msgstr "durée de l'adhésion"
 
-#: apps/member/models.py:198
+#: apps/member/models.py:201
 msgid "The longest time (in days) a membership can last (NULL = infinite)."
 msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)."
 
-#: apps/member/models.py:205 templates/member/club_info.html:23
+#: apps/member/models.py:208 templates/member/club_info.html:23
 msgid "membership start"
 msgstr "début de l'adhésion"
 
-#: apps/member/models.py:206
+#: apps/member/models.py:209
 msgid "How long after January 1st the members can renew their membership."
 msgstr ""
 "Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur "
 "adhésion."
 
-#: apps/member/models.py:213 templates/member/club_info.html:28
+#: apps/member/models.py:216 templates/member/club_info.html:28
 msgid "membership end"
 msgstr "fin de l'adhésion"
 
-#: apps/member/models.py:214
+#: apps/member/models.py:217
 msgid ""
 "How long the membership can last after January 1st of the next year after "
 "members can renew their membership."
@@ -533,46 +533,46 @@ msgstr ""
 "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année "
 "suivante avant que les adhérents peuvent renouveler leur adhésion."
 
-#: apps/member/models.py:248 apps/member/models.py:273
+#: apps/member/models.py:251 apps/member/models.py:276
 #: apps/note/models/notes.py:163
 msgid "club"
 msgstr "club"
 
-#: apps/member/models.py:249
+#: apps/member/models.py:252
 msgid "clubs"
 msgstr "clubs"
 
-#: apps/member/models.py:283
+#: apps/member/models.py:286
 msgid "membership starts on"
 msgstr "l'adhésion commence le"
 
-#: apps/member/models.py:287
+#: apps/member/models.py:290
 msgid "membership ends on"
 msgstr "l'adhésion finit le"
 
-#: apps/member/models.py:339
+#: apps/member/models.py:342
 #, python-brace-format
 msgid "The role {role} does not apply to the club {club}."
 msgstr "Le rôle {role} ne s'applique pas au club {club}."
 
-#: apps/member/models.py:350 apps/member/views.py:583
+#: apps/member/models.py:353 apps/member/views.py:589
 msgid "User is already a member of the club"
 msgstr "L'utilisateur est déjà membre du club"
 
-#: apps/member/models.py:386
+#: apps/member/models.py:400
 msgid "User is not a member of the parent club"
 msgstr "L'utilisateur n'est pas membre du club parent"
 
-#: apps/member/models.py:439
+#: apps/member/models.py:453
 #, python-brace-format
 msgid "Membership of {user} for the club {club}"
 msgstr "Adhésion de {user} pour le club {club}"
 
-#: apps/member/models.py:442
+#: apps/member/models.py:456
 msgid "membership"
 msgstr "adhésion"
 
-#: apps/member/models.py:443
+#: apps/member/models.py:457
 msgid "memberships"
 msgstr "adhésions"
 
@@ -590,47 +590,47 @@ msgstr "Modifier le profil"
 msgid "This address must be valid."
 msgstr "Cette adresse doit être valide."
 
-#: apps/member/views.py:128
+#: apps/member/views.py:134
 msgid "Profile detail"
 msgstr "Détails de l'utilisateur"
 
-#: apps/member/views.py:162
+#: apps/member/views.py:168
 msgid "Search user"
 msgstr "Chercher un utilisateur"
 
-#: apps/member/views.py:196 apps/member/views.py:382
+#: apps/member/views.py:202 apps/member/views.py:388
 msgid "Note aliases"
 msgstr "Alias de la note"
 
-#: apps/member/views.py:210
+#: apps/member/views.py:216
 msgid "Update note picture"
 msgstr "Modifier la photo de la note"
 
-#: apps/member/views.py:268 templates/member/profile_info.html:43
+#: apps/member/views.py:274 templates/member/profile_info.html:43
 msgid "Manage auth token"
 msgstr "Gérer les jetons d'authentification"
 
-#: apps/member/views.py:296
+#: apps/member/views.py:302
 msgid "Create new club"
 msgstr "Créer un nouveau club"
 
-#: apps/member/views.py:308
+#: apps/member/views.py:314
 msgid "Search club"
 msgstr "Chercher un club"
 
-#: apps/member/views.py:333
+#: apps/member/views.py:339
 msgid "Club detail"
 msgstr "Détails du club"
 
-#: apps/member/views.py:399
+#: apps/member/views.py:405
 msgid "Update club"
 msgstr "Modifier le club"
 
-#: apps/member/views.py:433
+#: apps/member/views.py:439
 msgid "Add new member to the club"
 msgstr "Ajouter un nouveau membre au club"
 
-#: apps/member/views.py:574 apps/wei/views.py:862
+#: apps/member/views.py:580 apps/wei/views.py:862
 msgid ""
 "This user don't have enough money to join this club, and can't have a "
 "negative balance."
@@ -638,25 +638,25 @@ msgstr ""
 "Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
 "avoir un solde négatif."
 
-#: apps/member/views.py:587
+#: apps/member/views.py:593
 msgid "The membership must start after {:%m-%d-%Y}."
 msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
 
-#: apps/member/views.py:592
+#: apps/member/views.py:598
 msgid "The membership must begin before {:%m-%d-%Y}."
 msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
 
-#: apps/member/views.py:609 apps/member/views.py:611 apps/member/views.py:613
+#: apps/member/views.py:615 apps/member/views.py:617 apps/member/views.py:619
 #: apps/registration/views.py:290 apps/registration/views.py:292
 #: apps/registration/views.py:294 apps/wei/views.py:867 apps/wei/views.py:871
 msgid "This field is required."
 msgstr "Ce champ est requis."
 
-#: apps/member/views.py:690
+#: apps/member/views.py:703
 msgid "Manage roles of an user in the club"
 msgstr "Gérer les rôles d'un utilisateur dans le club"
 
-#: apps/member/views.py:715
+#: apps/member/views.py:728
 msgid "Members of the club"
 msgstr "Membres du club"
 
@@ -1419,13 +1419,13 @@ msgstr "Liste des crédits de la Société générale"
 msgid "Manage credits from the Société générale"
 msgstr "Gérer les crédits de la Société générale"
 
-#: apps/wei/apps.py:10 apps/wei/models.py:48 apps/wei/models.py:49
-#: apps/wei/models.py:60 apps/wei/models.py:166 templates/base.html:124
+#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51
+#: apps/wei/models.py:62 apps/wei/models.py:168 templates/base.html:124
 msgid "WEI"
 msgstr "WEI"
 
-#: apps/wei/forms/registration.py:50 apps/wei/models.py:112
-#: apps/wei/models.py:297
+#: apps/wei/forms/registration.py:50 apps/wei/models.py:114
+#: apps/wei/models.py:299
 msgid "bus"
 msgstr "Bus"
 
@@ -1451,7 +1451,7 @@ msgstr ""
 "bus ou électron libre)"
 
 #: apps/wei/forms/registration.py:66 apps/wei/forms/registration.py:76
-#: apps/wei/models.py:147
+#: apps/wei/models.py:149
 msgid "WEI Roles"
 msgstr "Rôles au WEI"
 
@@ -1463,105 +1463,105 @@ msgstr "Sélectionnez les rôles qui vous intéressent."
 msgid "This team doesn't belong to the given bus."
 msgstr "Cette équipe n'appartient pas à ce bus."
 
-#: apps/wei/models.py:23 templates/wei/weiclub_info.html:23
+#: apps/wei/models.py:25 templates/wei/weiclub_info.html:23
 msgid "year"
 msgstr "année"
 
-#: apps/wei/models.py:27 templates/wei/weiclub_info.html:17
+#: apps/wei/models.py:29 templates/wei/weiclub_info.html:17
 msgid "date start"
 msgstr "début"
 
-#: apps/wei/models.py:31 templates/wei/weiclub_info.html:20
+#: apps/wei/models.py:33 templates/wei/weiclub_info.html:20
 msgid "date end"
 msgstr "fin"
 
-#: apps/wei/models.py:76
+#: apps/wei/models.py:78
 msgid "survey information"
 msgstr "informations sur le questionnaire"
 
-#: apps/wei/models.py:77
+#: apps/wei/models.py:79
 msgid "Information about the survey for new members, encoded in JSON"
 msgstr ""
 "Informations sur le sondage pour les nouveaux membres, encodées en JSON"
 
-#: apps/wei/models.py:99
+#: apps/wei/models.py:101
 msgid "Bus"
 msgstr "Bus"
 
-#: apps/wei/models.py:100 templates/wei/weiclub_tables.html:32
+#: apps/wei/models.py:102 templates/wei/weiclub_tables.html:32
 msgid "Buses"
 msgstr "Bus"
 
-#: apps/wei/models.py:121
+#: apps/wei/models.py:123
 msgid "color"
 msgstr "couleur"
 
-#: apps/wei/models.py:122
+#: apps/wei/models.py:124
 msgid "The color of the T-Shirt, stored with its number equivalent"
 msgstr ""
 "La couleur du T-Shirt, stocké sous la forme de son équivalent numérique"
 
-#: apps/wei/models.py:136
+#: apps/wei/models.py:138
 msgid "Bus team"
 msgstr "Équipe de bus"
 
-#: apps/wei/models.py:137
+#: apps/wei/models.py:139
 msgid "Bus teams"
 msgstr "Équipes de bus"
 
-#: apps/wei/models.py:146
+#: apps/wei/models.py:148
 msgid "WEI Role"
 msgstr "Rôle au WEI"
 
-#: apps/wei/models.py:171
+#: apps/wei/models.py:173
 msgid "Credit from Société générale"
 msgstr "Crédit de la Société générale"
 
-#: apps/wei/models.py:176
+#: apps/wei/models.py:178
 msgid "Caution check given"
 msgstr "Chèque de caution donné"
 
-#: apps/wei/models.py:180 templates/wei/weimembership_form.html:68
+#: apps/wei/models.py:182 templates/wei/weimembership_form.html:68
 msgid "birth date"
 msgstr "date de naissance"
 
-#: apps/wei/models.py:186 apps/wei/models.py:196
+#: apps/wei/models.py:188 apps/wei/models.py:198
 msgid "Male"
 msgstr "Homme"
 
-#: apps/wei/models.py:187 apps/wei/models.py:197
+#: apps/wei/models.py:189 apps/wei/models.py:199
 msgid "Female"
 msgstr "Femme"
 
-#: apps/wei/models.py:188
+#: apps/wei/models.py:190
 msgid "Non binary"
 msgstr "Non-binaire"
 
-#: apps/wei/models.py:190 templates/wei/weimembership_form.html:59
+#: apps/wei/models.py:192 templates/wei/weimembership_form.html:59
 msgid "gender"
 msgstr "genre"
 
-#: apps/wei/models.py:199 templates/wei/weimembership_form.html:62
+#: apps/wei/models.py:201 templates/wei/weimembership_form.html:62
 msgid "clothing cut"
 msgstr "coupe de vêtement"
 
-#: apps/wei/models.py:212 templates/wei/weimembership_form.html:65
+#: apps/wei/models.py:214 templates/wei/weimembership_form.html:65
 msgid "clothing size"
 msgstr "taille de vêtement"
 
-#: apps/wei/models.py:218 templates/wei/weimembership_form.html:71
+#: apps/wei/models.py:220 templates/wei/weimembership_form.html:71
 msgid "health issues"
 msgstr "problèmes de santé"
 
-#: apps/wei/models.py:223 templates/wei/weimembership_form.html:74
+#: apps/wei/models.py:225 templates/wei/weimembership_form.html:74
 msgid "emergency contact name"
 msgstr "Nom du contact en cas d'urgence"
 
-#: apps/wei/models.py:228 templates/wei/weimembership_form.html:77
+#: apps/wei/models.py:230 templates/wei/weimembership_form.html:77
 msgid "emergency contact phone"
 msgstr "Téléphone du contact en cas d'urgence"
 
-#: apps/wei/models.py:233 templates/wei/weimembership_form.html:80
+#: apps/wei/models.py:235 templates/wei/weimembership_form.html:80
 msgid ""
 "Register on the mailing list to stay informed of the events of the campus (1 "
 "mail/week)"
@@ -1569,7 +1569,7 @@ msgstr ""
 "S'inscrire sur la liste de diffusion pour rester informé des événements sur "
 "le campus (1 mail par semaine)"
 
-#: apps/wei/models.py:238 templates/wei/weimembership_form.html:83
+#: apps/wei/models.py:240 templates/wei/weimembership_form.html:83
 msgid ""
 "Register on the mailing list to stay informed of the sport events of the "
 "campus (1 mail/week)"
@@ -1577,7 +1577,7 @@ msgstr ""
 "S'inscrire sur la liste de diffusion pour rester informé des actualités "
 "sportives sur le campus (1 mail par semaine)"
 
-#: apps/wei/models.py:243 templates/wei/weimembership_form.html:86
+#: apps/wei/models.py:245 templates/wei/weimembership_form.html:86
 msgid ""
 "Register on the mailing list to stay informed of the art events of the "
 "campus (1 mail/week)"
@@ -1585,19 +1585,19 @@ msgstr ""
 "S'inscrire sur la liste de diffusion pour rester informé des actualités "
 "artistiques sur le campus (1 mail par semaine)"
 
-#: apps/wei/models.py:248 templates/wei/weimembership_form.html:56
+#: apps/wei/models.py:250 templates/wei/weimembership_form.html:56
 msgid "first year"
 msgstr "première année"
 
-#: apps/wei/models.py:249
+#: apps/wei/models.py:251
 msgid "Tells if the user is new in the school."
 msgstr "Indique si l'utilisateur est nouveau dans l'école."
 
-#: apps/wei/models.py:254
+#: apps/wei/models.py:256
 msgid "registration information"
 msgstr "informations sur l'inscription"
 
-#: apps/wei/models.py:255
+#: apps/wei/models.py:257
 msgid ""
 "Information about the registration (buses for old members, survey fot the "
 "new members), encoded in JSON"
@@ -1605,27 +1605,27 @@ msgstr ""
 "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les "
 "1A), encodées en JSON"
 
-#: apps/wei/models.py:286
+#: apps/wei/models.py:288
 msgid "WEI User"
 msgstr "Participant au WEI"
 
-#: apps/wei/models.py:287
+#: apps/wei/models.py:289
 msgid "WEI Users"
 msgstr "Participants au WEI"
 
-#: apps/wei/models.py:307
+#: apps/wei/models.py:309
 msgid "team"
 msgstr "équipe"
 
-#: apps/wei/models.py:317
+#: apps/wei/models.py:319
 msgid "WEI registration"
 msgstr "inscription au WEI"
 
-#: apps/wei/models.py:321
+#: apps/wei/models.py:323
 msgid "WEI membership"
 msgstr "adhésion au WEI"
 
-#: apps/wei/models.py:322
+#: apps/wei/models.py:324
 msgid "WEI memberships"
 msgstr "adhésions au WEI"
 
@@ -1765,15 +1765,15 @@ msgstr "Cet utilisateur n'a pas donné son chèque de caution."
 msgid "Survey WEI"
 msgstr "Questionnaire WEI"
 
-#: note_kfet/settings/base.py:156
+#: note_kfet/settings/base.py:157
 msgid "German"
 msgstr "Allemand"
 
-#: note_kfet/settings/base.py:157
+#: note_kfet/settings/base.py:158
 msgid "English"
 msgstr "Anglais"
 
-#: note_kfet/settings/base.py:158
+#: note_kfet/settings/base.py:159
 msgid "French"
 msgstr "Français"
 
@@ -2712,29 +2712,25 @@ msgstr ""
 "L'inscription va échouer."
 
 #: templates/wei/weimembership_form.html:169
-#, fuzzy, python-format
-#| msgid "The note has enough money, the registration is possible."
+#, python-format
 msgid ""
 "The note has enough money (%(pretty_fee)s required), the registration is "
 "possible."
-msgstr "La note a assez d'argent, l'inscription est possible."
+msgstr ""
+"La note a assez d'argent (%(pretty_fee) requis), l'inscription est possible."
 
 #: templates/wei/weimembership_form.html:178
 msgid "The user didn't give her/his caution check."
 msgstr "L'utilisateur n'a pas donné son chèque de caution."
 
 #: templates/wei/weimembership_form.html:186
-#, fuzzy
-#| msgid ""
-#| "You must also go to the Kfet to pay your membership. The WEI registration "
-#| "includes the BDE membership."
 msgid ""
 "This user is not a member of the Kfet club for the coming year. The "
 "membership will be processed automatically, the WEI registration includes "
 "the membership fee."
 msgstr ""
-"Vous devrez également vous rendre à la Kfet pour payer votre adhésion. "
-"L'inscription au WEI inclut l'adhésion au BDE."
+"Vous devrez également vous rendre à la Kfet pour payer votre adhésion pour "
+"l'année à venir. L'inscription au WEI inclut l'adhésion au BDE."
 
 #: templates/wei/weimembership_list.html:24
 msgid "View unvalidated registrations..."
@@ -2760,16 +2756,3 @@ msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée."
 #: templates/wei/weiregistration_list.html:24
 msgid "View validated memberships..."
 msgstr "Voir les adhésions validées ..."
-
-#~ msgid ""
-#~ "This user is not a member of the Kfet club for the comming year. Please "
-#~ "adhere <a href=\"%(future_user_detail)s\">here if he/she is in her/his "
-#~ "first year</a> or <a href=\"%(club_detail)s\">here if he/she was an old "
-#~ "member</a> before you validate the registration of the WEI."
-#~ msgstr ""
-#~ "Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. Merci "
-#~ "de le faire adhérer\n"
-#~ "<a href=\"%(future_user_detail)s\">ici s'iel est en première année</a>\n"
-#~ "ou <a href=\"%(club_detail)s\">ici s'iel est un ancien membre</a> avant "
-#~ "de valider\n"
-#~ "l'inscription au WEI."
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 3c557937..5df999fb 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -37,6 +37,7 @@ INSTALLED_APPS = [
 
     # External apps
     'mailer',
+    'phonenumber_field',
     'polymorphic',
     'crispy_forms',
     'django_tables2',
@@ -195,3 +196,7 @@ MEDIA_URL = '/media/'
 # Profile Picture Settings
 PIC_WIDTH = 200
 PIC_RATIO = 1
+
+
+PHONENUMBER_DB_FORMAT = 'NATIONAL'
+PHONENUMBER_DEFAULT_REGION = 'FR'
diff --git a/requirements/base.txt b/requirements/base.txt
index d6e5b075..eb03fbf1 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -7,11 +7,13 @@ django-crispy-forms==1.7.2
 django-extensions==2.1.9
 django-filter==2.2.0
 django-mailer==2.0.1
+django-phonenumber-field==4.0.0
 django-polymorphic==2.0.3
 django-tables2==2.1.0
 docutils==0.14
 idna==2.8
 oauthlib==3.1.0
+phonenumbers==8.12.7
 Pillow==7.1.2
 python3-openid==3.1.0
 pytz==2019.1
-- 
GitLab