From 7633c9ab4b44a49f0d39ce29368f1895fe2562b8 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Fri, 29 Aug 2025 18:33:05 +0200 Subject: [PATCH 01/19] Better phone input (no invalid number) --- apps/member/forms.py | 13 +++++- .../templates/member/profile_update.html | 44 ++++++++++++++++++- .../templates/wei/weiregistration_form.html | 42 +++++++++++++++++- note_kfet/settings/base.py | 4 +- note_kfet/templates/base.html | 4 ++ note_kfet/templates/registration/signup.html | 42 ++++++++++++++++++ 6 files changed, 144 insertions(+), 5 deletions(-) diff --git a/apps/member/forms.py b/apps/member/forms.py index c4940bf6..8735dc8e 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -10,6 +10,7 @@ from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.models import User from django.db import transaction from django.forms import CheckboxSelectMultiple +from phonenumber_field.formfields import PhoneNumberField from django.utils import timezone from django.utils.translation import gettext_lazy as _ from note.models import NoteSpecial, Alias @@ -45,6 +46,11 @@ class ProfileForm(forms.ModelForm): A form for the extras field provided by the :model:`member.Profile` model. """ # Remove widget=forms.HiddenInput() if you want to use report frequency. + phone_number = PhoneNumberField( + widget=forms.TextInput(attrs={"type": "tel", "class": "form-control"}), + required=False + ) + report_frequency = forms.IntegerField(required=False, initial=0, label=_("Report frequency")) last_report = forms.DateTimeField(required=False, disabled=True, label=_("Last report date")) @@ -72,7 +78,12 @@ class ProfileForm(forms.ModelForm): if not self.instance.section or (("department" in self.changed_data or "promotion" in self.changed_data) and "section" not in self.changed_data): self.instance.section = self.instance.section_generated - return super().save(commit) + instance = super().save(commit=False) + if instance.phone_number: + instance.phone_number = instance.phone_number.as_e164 + if commit: + instance.save() + return instance class Meta: model = Profile diff --git a/apps/member/templates/member/profile_update.html b/apps/member/templates/member/profile_update.html index 2f018381..e0975c22 100644 --- a/apps/member/templates/member/profile_update.html +++ b/apps/member/templates/member/profile_update.html @@ -10,7 +10,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {{ title }}
-
+ {% csrf_token %} {{ form | crispy }} {{ profile_form | crispy }} @@ -20,4 +20,46 @@ SPDX-License-Identifier: GPL-3.0-or-later
+{% endblock %} + +{% block extrajavascript %} + + {% endblock %} \ No newline at end of file diff --git a/apps/wei/templates/wei/weiregistration_form.html b/apps/wei/templates/wei/weiregistration_form.html index fae85e0f..4964814d 100644 --- a/apps/wei/templates/wei/weiregistration_form.html +++ b/apps/wei/templates/wei/weiregistration_form.html @@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {{ title }}
-
+ {% csrf_token %} {{ form|crispy }} {{ membership_form|crispy }} @@ -22,6 +22,46 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblock %} {% block extrajavascript %} + + + {% if not object.membership %} @@ -41,6 +43,8 @@ SPDX-License-Identifier: GPL-3.0-or-later {# Translation in javascript files #} + + {# If extra ressources are needed for a form, load here #} {% if form.media %} {{ form.media }} diff --git a/note_kfet/templates/registration/signup.html b/note_kfet/templates/registration/signup.html index 7bd503eb..8aa15f8c 100644 --- a/note_kfet/templates/registration/signup.html +++ b/note_kfet/templates/registration/signup.html @@ -31,3 +31,45 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endblock %} + +{% block extrajavascript %} + + +{% endblock %} \ No newline at end of file From 0934b8fa34a540bf83a39347ac60ccf5fbe8eacb Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Sat, 30 Aug 2025 16:15:55 +0200 Subject: [PATCH 02/19] Patch --- note_kfet/templates/registration/signup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/note_kfet/templates/registration/signup.html b/note_kfet/templates/registration/signup.html index 8aa15f8c..5428ff95 100644 --- a/note_kfet/templates/registration/signup.html +++ b/note_kfet/templates/registration/signup.html @@ -19,7 +19,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endblocktrans %} - + {% csrf_token %} {{ form|crispy }} {{ profile_form|crispy }} From 897d37f74dffdb30ff928c5631a6fb8fe0b24993 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Sun, 31 Aug 2025 21:41:35 +0200 Subject: [PATCH 03/19] New informative questions --- apps/wei/forms/surveys/wei2025.py | 54 ++++++++++++++++-- .../wei/img/logo_auvergne_rhone_alpes.jpg | Bin 0 -> 35259 bytes 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 apps/wei/static/wei/img/logo_auvergne_rhone_alpes.jpg diff --git a/apps/wei/forms/surveys/wei2025.py b/apps/wei/forms/surveys/wei2025.py index 67439b6e..758776b8 100644 --- a/apps/wei/forms/surveys/wei2025.py +++ b/apps/wei/forms/surveys/wei2025.py @@ -17,7 +17,7 @@ from ...models import WEIMembership, Bus WORDS = { 'list': [ - 'Fiesta', 'Graillance', 'Move it move it', 'Calme', 'Nert et geek', 'Jeux de rôles et danse rock', + 'Fiesta', 'Graillance', 'Move it move it', 'Calme', 'Nerd et geek', 'Jeux de rôles et danse rock', 'Strass et paillettes', 'Spectaculaire', 'Splendide', 'Flow inégalable', 'Rap', 'Battles légendaires', 'Techno', 'Alcool', 'Kiffeur·euse', 'Rugby', 'Médiéval', 'Festif', 'Stylé', 'Chipie', 'Rétro', 'Vache', 'Farfadet', 'Fanfare', @@ -57,7 +57,7 @@ WORDS = { 42: "Un burgouzz de valouzz", 47: "Un ocarina (pour me téléporter hors de ce bourbier)", 48: "Des paillettes, un micro de karaoké et une enceinte bluetooth", - 45: "", + 45: "Un kebab", 44: "Une 86 et un caisson pour taper du pied", 46: "Une épée, un ballon et une tireuse", 43: "Des lunettes de soleil", @@ -176,7 +176,33 @@ WORDS = { 49: "Soirée raclette !" } ] - } + }, + 'stats': [ + { + "question": """Le WEI est structuré par bus, et au sein de chaque bus, par équipes. + Pour toi, être dans une équipe où tout le monde reste sobre (primo-entrants comme encadrants) c'est :""", + "answers": [ + (1, "Inenvisageable"), + (2, "À contre cœur"), + (3, "Pourquoi pas"), + (4, "Souhaitable"), + (5, "Nécessaire"), + ], + "help_text": "(De toute façon aucun alcool n'est consommé pendant les trajets du bus, ni aller, ni retour.)", + }, + { + "question": "Faire partie d'un bus qui n'apporte pas de boisson alcoolisée pour ses membres, pour toi c'est :", + "answers": [ + (1, "Inenvisageable"), + (2, "À contre cœur"), + (3, "Pourquoi pas"), + (4, "Souhaitable"), + (5, "Nécessaire"), + ], + "help_text": """(Tout les bus apportent de l'alcool cette année, cette question sert à l'organisation pour l'année prochaine. + De plus il y aura de toute façon de l'alcool commun au WEI et aucun alcool n'est consommé pendant les trajets en bus.)""", + }, + ] } IMAGES = { @@ -235,7 +261,7 @@ class WEISurveyForm2025(forms.Form): all_preferred_words = WORDS['list'] rng.shuffle(all_preferred_words) self.fields["words"].choices = [(w, w) for w in all_preferred_words] - else: + elif information.step <= len(WORDS['questions']): questions = list(WORDS['questions'].items()) idx = information.step - 1 if idx < len(questions): @@ -251,6 +277,15 @@ class WEISurveyForm2025(forms.Form): widget=OptionalImageRadioSelect(images=IMAGES.get(q, {})), required=True, ) + elif information.step == len(WORDS['questions']) + 1: + for i, v in enumerate(WORDS['stats']): + self.fields[f'stat_{i}'] = forms.ChoiceField( + label=v['question'], + choices=v['answers'], + widget=forms.RadioSelect(), + required=False, + help_text=_(v.get('help_text', '')) + ) def clean_words(self): data = self.cleaned_data['words'] @@ -377,7 +412,7 @@ class WEISurvey2025(WEISurvey): setattr(self.information, "word" + str(i), word) self.information.step += 1 self.save() - else: + elif 1 <= self.information.step <= len(WORDS['questions']): questions = list(WORDS['questions'].keys()) idx = self.information.step - 1 if idx < len(questions): @@ -385,6 +420,13 @@ class WEISurvey2025(WEISurvey): setattr(self.information, q, form.cleaned_data[q]) self.information.step += 1 self.save() + else: + for i, __ in enumerate(WORDS['stats']): + ans = form.cleaned_data.get(f'stat_{i}') + if ans is not None: + setattr(self.information, f'stat_{i}', ans) + self.information.step += 1 + self.save() @classmethod def get_algorithm_class(cls): @@ -394,7 +436,7 @@ class WEISurvey2025(WEISurvey): """ The survey is complete once the bus is chosen. """ - return self.information.step > len(WORDS['questions']) + return self.information.step > len(WORDS['questions']) + 1 @classmethod @lru_cache() diff --git a/apps/wei/static/wei/img/logo_auvergne_rhone_alpes.jpg b/apps/wei/static/wei/img/logo_auvergne_rhone_alpes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d95f496b60e4a821f27f4537313a9486df5d356c GIT binary patch literal 35259 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 Date: Sun, 31 Aug 2025 22:04:45 +0200 Subject: [PATCH 04/19] tests --- apps/wei/tests/test_wei_algorithm_2025.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/wei/tests/test_wei_algorithm_2025.py b/apps/wei/tests/test_wei_algorithm_2025.py index e1eac7e0..97fac3b8 100644 --- a/apps/wei/tests/test_wei_algorithm_2025.py +++ b/apps/wei/tests/test_wei_algorithm_2025.py @@ -53,9 +53,11 @@ class TestWEIAlgorithm(TestCase): birth_date='2000-01-01', ) information = WEISurveyInformation2025(registration) - for j in range(1, 21): + for j in range(1, 1 + NB_WORDS): setattr(information, f'word{j}', random.choice(WORDS['list'])) - information.step = 20 + for q in WORDS['questions']: + setattr(information, q, random.choice(list(WORDS['questions'][q][1].keys()))) + information.step = len(WORDS['questions']) + 2 information.save(registration) registration.save() @@ -87,7 +89,7 @@ class TestWEIAlgorithm(TestCase): setattr(information, f'word{j}', random.choice(WORDS['list'])) for q in WORDS['questions']: setattr(information, q, random.choice(list(WORDS['questions'][q][1].keys()))) - information.step = len(WORDS['questions']) + 1 + information.step = len(WORDS['questions']) + 2 information.save(registration) registration.save() survey = WEISurvey2025(registration) From 8700144dea6dfb820450add7158168a719609efd Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Wed, 24 Sep 2025 21:48:56 +0200 Subject: [PATCH 05/19] Permissions --- apps/permission/fixtures/initial.json | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json index e642c4e6..f3d4cf33 100644 --- a/apps/permission/fixtures/initial.json +++ b/apps/permission/fixtures/initial.json @@ -4833,7 +4833,10 @@ 221, 247, 258, - 259 + 259, + 260, + 263, + 265 ] } }, @@ -4845,7 +4848,6 @@ "name": "Pr\u00e9sident\u22c5e de club", "permissions": [ 62, - 135, 142 ] } @@ -5122,7 +5124,8 @@ 289, 290, 291, - 293 + 293, + 298 ] } }, @@ -5233,7 +5236,9 @@ 168, 176, 177, - 197 + 197, + 311, + 319 ] } }, @@ -5313,7 +5318,8 @@ 289, 290, 291, - 293 + 293, + 298 ] } }, From 5d8720cf462ac91fdcb7c83b337e0e9e7f41885a Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Wed, 24 Sep 2025 22:22:23 +0200 Subject: [PATCH 06/19] Phone input without permission fixed --- apps/member/templates/member/profile_update.html | 4 ++-- apps/wei/templates/wei/weiregistration_form.html | 4 ++-- note_kfet/templates/registration/signup.html | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/member/templates/member/profile_update.html b/apps/member/templates/member/profile_update.html index e0975c22..36029cb3 100644 --- a/apps/member/templates/member/profile_update.html +++ b/apps/member/templates/member/profile_update.html @@ -29,8 +29,8 @@ SPDX-License-Identifier: GPL-3.0-or-later const input = document.querySelector("input[name='phone_number']"); const form = document.querySelector("#profile-form"); - if (!input || !form) { - console.error("Input phone_number ou form introuvable."); + if (!input || !form || input.type === "hidden" || input.disabled || input.readOnly) { + return; } const iti = window.intlTelInput(input, { diff --git a/apps/wei/templates/wei/weiregistration_form.html b/apps/wei/templates/wei/weiregistration_form.html index 4964814d..dc5f66e5 100644 --- a/apps/wei/templates/wei/weiregistration_form.html +++ b/apps/wei/templates/wei/weiregistration_form.html @@ -28,8 +28,8 @@ SPDX-License-Identifier: GPL-3.0-or-later const input = document.querySelector("input[name='emergency_contact_phone']"); const form = document.querySelector("#registration-form"); - if (!input || !form) { - console.error("Input phone_number ou form introuvable."); + if (!input || !form || input.type === "hidden" || input.disabled || input.readOnly) { + return; } const iti = window.intlTelInput(input, { diff --git a/note_kfet/templates/registration/signup.html b/note_kfet/templates/registration/signup.html index 5428ff95..71fe2511 100644 --- a/note_kfet/templates/registration/signup.html +++ b/note_kfet/templates/registration/signup.html @@ -39,8 +39,8 @@ SPDX-License-Identifier: GPL-3.0-or-later const input = document.querySelector("input[name='phone_number']"); const form = document.querySelector("#profile_form"); - if (!input || !form) { - console.error("Input phone_number ou form introuvable."); + if (!input || !form || input.type === "hidden" || input.disabled || input.readOnly) { + return; } const iti = window.intlTelInput(input, { From 47d2476b51c6a10f4e95230c14d657a3af5227f0 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Thu, 25 Sep 2025 00:08:56 +0200 Subject: [PATCH 07/19] Allow to view activity entries on Activity tab --- .../activity/includes/activity_info.html | 8 +++++++- apps/activity/templatetags/__init__.py | 0 apps/activity/templatetags/dict_get.py | 12 ++++++++++++ apps/activity/views.py | 19 +++++++++++++++++++ apps/permission/fixtures/initial.json | 16 ++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 apps/activity/templatetags/__init__.py create mode 100644 apps/activity/templatetags/dict_get.py diff --git a/apps/activity/templates/activity/includes/activity_info.html b/apps/activity/templates/activity/includes/activity_info.html index f9ea634b..4565a086 100644 --- a/apps/activity/templates/activity/includes/activity_info.html +++ b/apps/activity/templates/activity/includes/activity_info.html @@ -1,7 +1,7 @@ {% comment %} SPDX-License-Identifier: GPL-3.0-or-later {% endcomment %} -{% load i18n perms pretty_money %} +{% load i18n perms pretty_money dict_get %} {% url 'activity:activity_detail' activity.pk as activity_detail_url %}
@@ -53,6 +53,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% trans 'opened'|capfirst %}
{{ activity.open|yesno }}
+ {% if show_entries|dict_get:activity %} +

+ {{ entries_count|dict_get:activity }} + {% if entries_count|dict_get:activity >= 2 %}{% trans "entries" %}{% else %}{% trans "entry" %}{% endif %} +

+ {% endif %}
+ +{{ block.super }} {% endblock %} diff --git a/apps/activity/views.py b/apps/activity/views.py index 9011f0e1..9ef0d4f2 100644 --- a/apps/activity/views.py +++ b/apps/activity/views.py @@ -67,27 +67,49 @@ class ActivityListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin tables = [ lambda data: ActivityTable(data, prefix="all-"), lambda data: ActivityTable(data, prefix="upcoming-"), + lambda data: ActivityTable(data, prefix="search-"), ] extra_context = {"title": _("Activities")} def get_queryset(self, **kwargs): - return super().get_queryset(**kwargs).distinct() + """ + Filter the user list with the given pattern. + """ + return super().get_queryset().distinct() def get_tables_data(self): - # first table = all activities, second table = upcoming + # first table = all activities, second table = upcoming, third table = search + + # table search + qs = self.get_queryset().order_by('-date_start') + if "search" in self.request.GET and self.request.GET['search']: + pattern = self.request.GET['search'] + + # check regex + valid_regex = is_regex(pattern) + suffix = '__iregex' if valid_regex else '__istartswith' + prefix = '^' if valid_regex else '' + qs = qs.filter(Q(**{f'name{suffix}': prefix + pattern}) + | Q(**{f'organizer__name{suffix}': prefix + pattern}) + | Q(**{f'organizer__note__alias__name{suffix}': prefix + pattern})) + else: + qs = qs.none() + search_table = qs.filter(PermissionBackend.filter_queryset(self.request, Activity, 'view')) + return [ self.get_queryset().order_by("-date_start"), Activity.objects.filter(date_end__gt=timezone.now()) .filter(PermissionBackend.filter_queryset(self.request, Activity, "view")) .distinct() - .order_by("date_start") + .order_by("date_start"), + search_table, ] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) tables = context["tables"] - for name, table in zip(["table", "upcoming"], tables): + for name, table in zip(["all", "upcoming", "table"], tables): context[name] = table started_activities = self.get_queryset().filter(open=True, valid=True).distinct().all() From 9907cfbd860985530f6af2329524918c62acb911 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Sat, 27 Sep 2025 01:17:33 +0200 Subject: [PATCH 09/19] Autocomplete Credit reason with 'Rechargement note' --- apps/note/static/note/js/transfer.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/note/static/note/js/transfer.js b/apps/note/static/note/js/transfer.js index 509d9b48..ce6ff6ff 100644 --- a/apps/note/static/note/js/transfer.js +++ b/apps/note/static/note/js/transfer.js @@ -66,6 +66,8 @@ $(document).ready(function () { arr.push(last) last.quantity = 1 + + if (last.note.club) { $('#last_name').val(last.note.name) @@ -111,7 +113,8 @@ $(document).ready(function () { dest.removeClass('d-none') $('#dest_note_list').removeClass('d-none') $('#debit_type').addClass('d-none') - + $('#reason').val('') + $('#source_note_label').text(select_emitters_label) $('#dest_note_label').text(select_receveirs_label) @@ -134,6 +137,7 @@ $(document).ready(function () { dest.val('') dest.tooltip('hide') $('#debit_type').addClass('d-none') + $('#reason').val('Rechargement note') $('#source_note_label').text(transfer_type_label) $('#dest_note_label').text(select_receveir_label) @@ -162,6 +166,7 @@ $(document).ready(function () { dest.addClass('d-none') dest.tooltip('hide') $('#debit_type').removeClass('d-none') + $('#reason').val('') $('#source_note_label').text(select_emitter_label) $('#dest_note_label').text(transfer_type_label) From 0962a3735eb025cb811d9071e3691ec2d74229b4 Mon Sep 17 00:00:00 2001 From: Ehouarn Date: Sat, 27 Sep 2025 13:19:48 +0200 Subject: [PATCH 10/19] Better Food search --- apps/food/tables.py | 18 +++++++++++++++++- apps/food/templates/food/food_list.html | 25 +++++++++++++++++++++++++ apps/food/views.py | 9 +++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/apps/food/tables.py b/apps/food/tables.py index 7789ad76..5b854e64 100644 --- a/apps/food/tables.py +++ b/apps/food/tables.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ from .models import Food @@ -10,10 +11,25 @@ class FoodTable(tables.Table): """ List all foods. """ + qr_code_numbers = tables.Column(empty_values=(), verbose_name=_("QR Codes"), orderable=False) + + date = tables.Column(empty_values=(), verbose_name=_("Arrival/creation date"), orderable=False) + + def render_date(self, record): + if record.__class__.__name__ == "BasicFood": + return record.arrival_date.strftime("%d/%m/%Y %H:%M") + elif record.__class__.__name__ == "TransformedFood": + return record.creation_date.strftime("%d/%m/%Y %H:%M") + else: + return "--" + + def render_qr_code_numbers(self, record): + return ", ".join(str(q.qr_code_number) for q in record.QR_code.all()) + class Meta: model = Food template_name = 'django_tables2/bootstrap4.html' - fields = ('name', 'owner', 'allergens', 'expiry_date') + fields = ('name', 'owner', 'qr_code_numbers', 'allergens', 'date', 'expiry_date') row_attrs = { 'class': 'table-row', 'data-href': lambda record: 'detail/' + str(record.pk), diff --git a/apps/food/templates/food/food_list.html b/apps/food/templates/food/food_list.html index bd54ece9..8e52a00a 100644 --- a/apps/food/templates/food/food_list.html +++ b/apps/food/templates/food/food_list.html @@ -34,6 +34,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
+
+ +
@@ -114,7 +120,26 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %} +