From fb5796d35e880d78645ad3b9cd0dd3206250a4c8 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 30 Mar 2020 00:42:32 +0200 Subject: [PATCH] Guests can't be invited more than 5 times a year and a member can't invite more than 3 people per activity. --- apps/activity/forms.py | 35 ++++- apps/activity/models.py | 26 +++- apps/activity/views.py | 5 + apps/member/forms.py | 4 +- apps/note/forms.py | 4 +- apps/note/models/notes.py | 31 +++++ locale/de/LC_MESSAGES/django.po | 160 ++++++++++++---------- locale/fr/LC_MESSAGES/django.po | 162 +++++++++++++---------- note_kfet/inputs.py | 8 +- templates/member/autocomplete_model.html | 2 +- 10 files changed, 279 insertions(+), 158 deletions(-) diff --git a/apps/activity/forms.py b/apps/activity/forms.py index c5a9e7f3..533ff7d1 100644 --- a/apps/activity/forms.py +++ b/apps/activity/forms.py @@ -1,11 +1,13 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from datetime import timedelta from django import forms from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext as _ from member.models import Club from note.models import NoteUser, Note -from note_kfet.inputs import DateTimePickerInput, AutocompleteModelSelect +from note_kfet.inputs import DateTimePickerInput, Autocomplete from .models import Activity, Guest @@ -15,18 +17,18 @@ class ActivityForm(forms.ModelForm): model = Activity exclude = ('creater', 'valid', 'open', ) widgets = { - "organizer": AutocompleteModelSelect( + "organizer": Autocomplete( model=Club, attrs={"api_url": "/api/members/club/"}, ), - "note": AutocompleteModelSelect( + "note": Autocomplete( model=Note, attrs={ "api_url": "/api/note/note/", 'placeholder': 'Note de l\'événement sur laquelle envoyer les crédits d\'invitation ...' }, ), - "attendees_club": AutocompleteModelSelect( + "attendees_club": Autocomplete( model=Club, attrs={"api_url": "/api/members/club/"}, ), @@ -36,11 +38,34 @@ class ActivityForm(forms.ModelForm): class GuestForm(forms.ModelForm): + def clean(self): + cleaned_data = super().clean() + + one_year = timedelta(days=365) + + qs = Guest.objects.filter( + first_name=cleaned_data["first_name"], + last_name=cleaned_data["last_name"], + activity__date_start__gte=self.activity.date_start - one_year, + ) + if len(qs) >= 5: + self.add_error("last_name", _("This person has been already invited 5 times this year.")) + + qs = qs.filter(activity=self.activity) + if qs.exists(): + self.add_error("last_name", _("This person is already invited.")) + + qs = Guest.objects.filter(inviter=cleaned_data["inviter"], activity=self.activity) + if len(qs) >= 3: + self.add_error("inviter", _("You can't invite more than 3 people to this activity.")) + + return cleaned_data + class Meta: model = Guest fields = ('last_name', 'first_name', 'inviter', ) widgets = { - "inviter": AutocompleteModelSelect( + "inviter": Autocomplete( NoteUser, attrs={ 'api_url': '/api/note/note/', diff --git a/apps/activity/models.py b/apps/activity/models.py index 948e0919..feae60d7 100644 --- a/apps/activity/models.py +++ b/apps/activity/models.py @@ -1,5 +1,6 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from datetime import timedelta from django.contrib.auth.models import User from django.db import models @@ -115,6 +116,7 @@ class Entry(models.Model): activity = models.ForeignKey( Activity, on_delete=models.PROTECT, + related_name="entries", verbose_name=_("activity"), ) @@ -194,7 +196,7 @@ class Guest(models.Model): inviter = models.ForeignKey( NoteUser, on_delete=models.PROTECT, - related_name='+', + related_name='guests', verbose_name=_("inviter"), ) @@ -207,9 +209,31 @@ class Guest(models.Model): except AttributeError: return False + def save(self, force_insert=False, force_update=False, using=None, update_fields=None): + one_year = timedelta(days=365) + + qs = Guest.objects.filter( + first_name=self.first_name, + last_name=self.last_name, + activity__date_start__gte=self.activity.date_start - one_year, + ) + if len(qs) >= 5: + raise ValidationError(_("This person has been already invited 5 times this year.")) + + qs = qs.filter(activity=self.activity) + if qs.exists(): + raise ValidationError(_("This person is already invited.")) + + qs = Guest.objects.filter(inviter=self.inviter, activity=self.activity) + if len(qs) >= 3: + raise ValidationError(_("You can't invite more than 3 people to this activity.")) + + return super().save(force_insert, force_update, using, update_fields) + class Meta: verbose_name = _("guest") verbose_name_plural = _("guests") + unique_together = ("activity", "last_name", "first_name", ) class GuestTransaction(Transaction): diff --git a/apps/activity/views.py b/apps/activity/views.py index 518d7c10..5df3493c 100644 --- a/apps/activity/views.py +++ b/apps/activity/views.py @@ -77,6 +77,11 @@ class ActivityInviteView(LoginRequiredMixin, CreateView): form_class = GuestForm template_name = "activity/activity_invite.html" + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.activity = Activity.objects.get(pk=self.kwargs["pk"]) + return form + def form_valid(self, form): form.instance.activity = Activity.objects.get(pk=self.kwargs["pk"]) return super().form_valid(form) diff --git a/apps/member/forms.py b/apps/member/forms.py index 76cd146b..20f0acfe 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -7,7 +7,7 @@ from crispy_forms.layout import Layout from django import forms from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth.models import User -from note_kfet.inputs import AutocompleteModelSelect +from note_kfet.inputs import Autocomplete from permission.models import PermissionMask from .models import Profile, Club, Membership @@ -63,7 +63,7 @@ class MembershipForm(forms.ModelForm): # et récupère les noms d'utilisateur valides widgets = { 'user': - AutocompleteModelSelect( + Autocomplete( User, attrs={ 'api_url': '/api/user/', diff --git a/apps/note/forms.py b/apps/note/forms.py index 8c9a04ce..50f226f2 100644 --- a/apps/note/forms.py +++ b/apps/note/forms.py @@ -4,7 +4,7 @@ from django import forms from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ -from note_kfet.inputs import AutocompleteModelSelect +from note_kfet.inputs import Autocomplete from .models import TransactionTemplate, NoteClub @@ -31,7 +31,7 @@ class TransactionTemplateForm(forms.ModelForm): # forward=(forward.Const('TYPE', 'note_type') où TYPE est dans {user, club, special} widgets = { 'destination': - AutocompleteModelSelect( + Autocomplete( NoteClub, attrs={ 'api_url': '/api/note/note/', diff --git a/apps/note/models/notes.py b/apps/note/models/notes.py index 9282bde9..d74d9147 100644 --- a/apps/note/models/notes.py +++ b/apps/note/models/notes.py @@ -10,6 +10,8 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from polymorphic.models import PolymorphicModel +from member.models import Club + """ Defines each note types """ @@ -174,6 +176,35 @@ class NoteSpecial(Note): return self.special_type +class NoteCommon(Note): + """ + A :model:`note.Note` for special accounts, where real money enter or leave the system + - bank check + - credit card + - bank transfer + - cash + - refund + This Type of Note is not associated to a :model:`auth.User` or :model:`member.Club` . + """ + note_name = models.CharField( + max_length=255, + unique=True, + ) + + club = models.ForeignKey( + Club, + on_delete=models.PROTECT, + verbose_name=_("club"), + ) + + class Meta: + verbose_name = _("common note") + verbose_name_plural = _("common notes") + + def __str__(self): + return self.note_name + + class Alias(models.Model): """ points toward a :model:`note.NoteUser` or :model;`note.NoteClub` instance. diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index f92240d3..49359fb1 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-03-28 16:42+0100\n" +"POT-Creation-Date: 2020-03-30 00:38+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,117 +18,134 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: apps/activity/apps.py:10 apps/activity/models.py:101 -#: apps/activity/models.py:109 +#: apps/activity/apps.py:10 apps/activity/models.py:111 +#: apps/activity/models.py:120 msgid "activity" msgstr "" -#: apps/activity/models.py:21 apps/activity/models.py:46 +#: apps/activity/forms.py:52 apps/activity/models.py:221 +msgid "This person has been already invited 5 times this year." +msgstr "" + +#: apps/activity/forms.py:56 apps/activity/models.py:225 +msgid "This person is already invited." +msgstr "" + +#: apps/activity/forms.py:60 apps/activity/models.py:229 +msgid "You can't invite more than 3 people to this activity." +msgstr "" + +#: apps/activity/models.py:23 apps/activity/models.py:48 #: apps/member/models.py:64 apps/member/models.py:122 -#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24 +#: apps/note/models/notes.py:219 apps/note/models/transactions.py:24 #: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231 #: templates/member/club_info.html:13 templates/member/profile_info.html:14 msgid "name" msgstr "" -#: apps/activity/models.py:25 templates/activity/activity_detail.html:34 +#: apps/activity/models.py:27 templates/activity/activity_detail.html:39 msgid "can invite" msgstr "" -#: apps/activity/models.py:28 templates/activity/activity_detail.html:38 +#: apps/activity/models.py:30 templates/activity/activity_detail.html:43 msgid "guest entry fee" msgstr "" -#: apps/activity/models.py:32 +#: apps/activity/models.py:34 msgid "activity type" msgstr "" -#: apps/activity/models.py:33 +#: apps/activity/models.py:35 msgid "activity types" msgstr "" -#: apps/activity/models.py:51 apps/note/models/transactions.py:69 +#: apps/activity/models.py:53 apps/note/models/transactions.py:69 #: apps/permission/models.py:90 templates/activity/activity_detail.html:16 msgid "description" msgstr "" -#: apps/activity/models.py:58 apps/note/models/notes.py:164 +#: apps/activity/models.py:60 apps/note/models/notes.py:166 #: apps/note/models/transactions.py:62 #: templates/activity/activity_detail.html:19 msgid "type" msgstr "" -#: apps/activity/models.py:65 templates/activity/activity_detail.html:28 +#: apps/activity/models.py:66 apps/logs/models.py:21 +#: apps/note/models/notes.py:119 +msgid "user" +msgstr "" + +#: apps/activity/models.py:73 templates/activity/activity_detail.html:33 msgid "organizer" msgstr "" -#: apps/activity/models.py:72 apps/activity/models.py:120 apps/note/apps.py:14 -#: apps/note/models/notes.py:58 +#: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14 +#: apps/note/models/notes.py:60 msgid "note" msgstr "" -#: apps/activity/models.py:79 templates/activity/activity_detail.html:31 +#: apps/activity/models.py:89 templates/activity/activity_detail.html:36 msgid "attendees club" msgstr "" -#: apps/activity/models.py:83 templates/activity/activity_detail.html:22 +#: apps/activity/models.py:93 templates/activity/activity_detail.html:22 msgid "start date" msgstr "" -#: apps/activity/models.py:87 templates/activity/activity_detail.html:25 +#: apps/activity/models.py:97 templates/activity/activity_detail.html:25 msgid "end date" msgstr "" -#: apps/activity/models.py:92 apps/note/models/transactions.py:134 -#: templates/activity/activity_detail.html:42 +#: apps/activity/models.py:102 apps/note/models/transactions.py:134 +#: templates/activity/activity_detail.html:47 msgid "valid" msgstr "" -#: apps/activity/models.py:97 templates/activity/activity_detail.html:56 +#: apps/activity/models.py:107 templates/activity/activity_detail.html:61 msgid "open" msgstr "" -#: apps/activity/models.py:102 +#: apps/activity/models.py:112 msgid "activities" msgstr "" -#: apps/activity/models.py:114 +#: apps/activity/models.py:125 msgid "entry time" msgstr "" -#: apps/activity/models.py:137 +#: apps/activity/models.py:148 msgid "Already entered on " msgstr "" -#: apps/activity/models.py:137 apps/activity/tables.py:54 +#: apps/activity/models.py:148 apps/activity/tables.py:54 msgid "{:%Y-%m-%d %H:%M:%S}" msgstr "" -#: apps/activity/models.py:145 +#: apps/activity/models.py:156 msgid "The balance is negative." msgstr "" -#: apps/activity/models.py:177 +#: apps/activity/models.py:188 msgid "last name" msgstr "" -#: apps/activity/models.py:182 templates/member/profile_info.html:14 +#: apps/activity/models.py:193 templates/member/profile_info.html:14 msgid "first name" msgstr "" -#: apps/activity/models.py:189 +#: apps/activity/models.py:200 msgid "inviter" msgstr "" -#: apps/activity/models.py:202 +#: apps/activity/models.py:234 msgid "guest" msgstr "" -#: apps/activity/models.py:203 +#: apps/activity/models.py:235 msgid "guests" msgstr "" -#: apps/activity/models.py:214 +#: apps/activity/models.py:247 msgid "Invitation" msgstr "" @@ -153,7 +170,7 @@ msgstr "" msgid "First name" msgstr "" -#: apps/activity/tables.py:81 apps/note/models/notes.py:67 +#: apps/activity/tables.py:81 apps/note/models/notes.py:69 msgid "Note" msgstr "" @@ -161,11 +178,11 @@ msgstr "" msgid "Balance" msgstr "" -#: apps/activity/views.py:35 templates/base.html:94 +#: apps/activity/views.py:44 templates/base.html:94 msgid "Activities" msgstr "" -#: apps/activity/views.py:130 +#: apps/activity/views.py:147 msgid "Entry for activity \"{}\"" msgstr "" @@ -177,10 +194,6 @@ msgstr "" msgid "Logs" msgstr "" -#: apps/logs/models.py:21 apps/note/models/notes.py:117 -msgid "user" -msgstr "" - #: apps/logs/models.py:27 msgid "IP Address" msgstr "" @@ -206,7 +219,7 @@ msgid "create" msgstr "" #: apps/logs/models.py:61 apps/note/tables.py:142 -#: templates/activity/activity_detail.html:62 +#: templates/activity/activity_detail.html:67 msgid "edit" msgstr "" @@ -292,7 +305,8 @@ msgid "" "members can renew their membership." msgstr "" -#: apps/member/models.py:104 apps/note/models/notes.py:139 +#: apps/member/models.py:104 apps/note/models/notes.py:141 +#: apps/note/models/notes.py:197 msgid "club" msgstr "" @@ -357,104 +371,104 @@ msgstr "" msgid "Maximal size: 2MB" msgstr "" -#: apps/note/models/notes.py:27 +#: apps/note/models/notes.py:29 msgid "account balance" msgstr "" -#: apps/note/models/notes.py:28 +#: apps/note/models/notes.py:30 msgid "in centimes, money credited for this instance" msgstr "" -#: apps/note/models/notes.py:32 +#: apps/note/models/notes.py:34 msgid "last negative date" msgstr "" -#: apps/note/models/notes.py:33 +#: apps/note/models/notes.py:35 msgid "last time the balance was negative" msgstr "" -#: apps/note/models/notes.py:38 +#: apps/note/models/notes.py:40 msgid "active" msgstr "" -#: apps/note/models/notes.py:41 +#: apps/note/models/notes.py:43 msgid "" "Designates whether this note should be treated as active. Unselect this " "instead of deleting notes." msgstr "" -#: apps/note/models/notes.py:45 +#: apps/note/models/notes.py:47 msgid "display image" msgstr "" -#: apps/note/models/notes.py:53 apps/note/models/transactions.py:117 +#: apps/note/models/notes.py:55 apps/note/models/transactions.py:117 msgid "created at" msgstr "" -#: apps/note/models/notes.py:59 +#: apps/note/models/notes.py:61 msgid "notes" msgstr "" -#: apps/note/models/notes.py:77 apps/note/models/notes.py:101 +#: apps/note/models/notes.py:79 apps/note/models/notes.py:103 msgid "This alias is already taken." msgstr "" -#: apps/note/models/notes.py:121 +#: apps/note/models/notes.py:123 msgid "one's note" msgstr "" -#: apps/note/models/notes.py:122 +#: apps/note/models/notes.py:124 msgid "users note" msgstr "" -#: apps/note/models/notes.py:128 +#: apps/note/models/notes.py:130 #, python-format msgid "%(user)s's note" msgstr "" -#: apps/note/models/notes.py:143 +#: apps/note/models/notes.py:145 msgid "club note" msgstr "" -#: apps/note/models/notes.py:144 +#: apps/note/models/notes.py:146 msgid "clubs notes" msgstr "" -#: apps/note/models/notes.py:150 +#: apps/note/models/notes.py:152 #, python-format msgid "Note of %(club)s club" msgstr "" -#: apps/note/models/notes.py:170 +#: apps/note/models/notes.py:172 msgid "special note" msgstr "" -#: apps/note/models/notes.py:171 +#: apps/note/models/notes.py:173 msgid "special notes" msgstr "" -#: apps/note/models/notes.py:194 +#: apps/note/models/notes.py:225 msgid "Invalid alias" msgstr "" -#: apps/note/models/notes.py:210 +#: apps/note/models/notes.py:241 msgid "alias" msgstr "" -#: apps/note/models/notes.py:211 templates/member/club_info.html:33 +#: apps/note/models/notes.py:242 templates/member/club_info.html:33 #: templates/member/profile_info.html:36 msgid "aliases" msgstr "" -#: apps/note/models/notes.py:233 +#: apps/note/models/notes.py:264 msgid "Alias is too long." msgstr "" -#: apps/note/models/notes.py:238 +#: apps/note/models/notes.py:269 msgid "An alias with a similar name already exists: {} " msgstr "" -#: apps/note/models/notes.py:251 +#: apps/note/models/notes.py:282 msgid "You can't delete your main alias." msgstr "" @@ -727,31 +741,35 @@ msgstr "" msgid "French" msgstr "" -#: templates/activity/activity_detail.html:45 +#: templates/activity/activity_detail.html:29 +msgid "creater" +msgstr "" + +#: templates/activity/activity_detail.html:50 msgid "opened" msgstr "" -#: templates/activity/activity_detail.html:52 +#: templates/activity/activity_detail.html:57 msgid "Entry page" msgstr "" -#: templates/activity/activity_detail.html:56 +#: templates/activity/activity_detail.html:61 msgid "close" msgstr "" -#: templates/activity/activity_detail.html:59 +#: templates/activity/activity_detail.html:64 msgid "invalidate" msgstr "" -#: templates/activity/activity_detail.html:59 +#: templates/activity/activity_detail.html:64 msgid "validate" msgstr "" -#: templates/activity/activity_detail.html:65 +#: templates/activity/activity_detail.html:70 msgid "Invite" msgstr "" -#: templates/activity/activity_detail.html:72 +#: templates/activity/activity_detail.html:77 msgid "Guests list" msgstr "" diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 4a900f35..8a6fa1f8 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-03-28 16:42+0100\n" +"POT-Creation-Date: 2020-03-30 00:38+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -13,117 +13,134 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: apps/activity/apps.py:10 apps/activity/models.py:101 -#: apps/activity/models.py:109 +#: apps/activity/apps.py:10 apps/activity/models.py:111 +#: apps/activity/models.py:120 msgid "activity" msgstr "activité" -#: apps/activity/models.py:21 apps/activity/models.py:46 +#: apps/activity/forms.py:52 apps/activity/models.py:221 +msgid "This person has been already invited 5 times this year." +msgstr "Cette personne a déjà été invitée 5 fois cette année." + +#: apps/activity/forms.py:56 apps/activity/models.py:225 +msgid "This person is already invited." +msgstr "Cette personne est déjà invitée." + +#: apps/activity/forms.py:60 apps/activity/models.py:229 +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:23 apps/activity/models.py:48 #: apps/member/models.py:64 apps/member/models.py:122 -#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24 +#: apps/note/models/notes.py:219 apps/note/models/transactions.py:24 #: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231 #: templates/member/club_info.html:13 templates/member/profile_info.html:14 msgid "name" msgstr "nom" -#: apps/activity/models.py:25 templates/activity/activity_detail.html:34 +#: apps/activity/models.py:27 templates/activity/activity_detail.html:39 msgid "can invite" msgstr "peut inviter" -#: apps/activity/models.py:28 templates/activity/activity_detail.html:38 +#: apps/activity/models.py:30 templates/activity/activity_detail.html:43 msgid "guest entry fee" msgstr "cotisation de l'entrée invité" -#: apps/activity/models.py:32 +#: apps/activity/models.py:34 msgid "activity type" msgstr "type d'activité" -#: apps/activity/models.py:33 +#: apps/activity/models.py:35 msgid "activity types" msgstr "types d'activité" -#: apps/activity/models.py:51 apps/note/models/transactions.py:69 +#: apps/activity/models.py:53 apps/note/models/transactions.py:69 #: apps/permission/models.py:90 templates/activity/activity_detail.html:16 msgid "description" msgstr "description" -#: apps/activity/models.py:58 apps/note/models/notes.py:164 +#: apps/activity/models.py:60 apps/note/models/notes.py:166 #: apps/note/models/transactions.py:62 #: templates/activity/activity_detail.html:19 msgid "type" msgstr "type" -#: apps/activity/models.py:65 templates/activity/activity_detail.html:28 +#: apps/activity/models.py:66 apps/logs/models.py:21 +#: apps/note/models/notes.py:119 +msgid "user" +msgstr "utilisateur" + +#: apps/activity/models.py:73 templates/activity/activity_detail.html:33 msgid "organizer" msgstr "organisateur" -#: apps/activity/models.py:72 apps/activity/models.py:120 apps/note/apps.py:14 -#: apps/note/models/notes.py:58 +#: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14 +#: apps/note/models/notes.py:60 msgid "note" msgstr "note" -#: apps/activity/models.py:79 templates/activity/activity_detail.html:31 +#: apps/activity/models.py:89 templates/activity/activity_detail.html:36 msgid "attendees club" msgstr "club attendu" -#: apps/activity/models.py:83 templates/activity/activity_detail.html:22 +#: apps/activity/models.py:93 templates/activity/activity_detail.html:22 msgid "start date" msgstr "date de début" -#: apps/activity/models.py:87 templates/activity/activity_detail.html:25 +#: apps/activity/models.py:97 templates/activity/activity_detail.html:25 msgid "end date" msgstr "date de fin" -#: apps/activity/models.py:92 apps/note/models/transactions.py:134 -#: templates/activity/activity_detail.html:42 +#: apps/activity/models.py:102 apps/note/models/transactions.py:134 +#: templates/activity/activity_detail.html:47 msgid "valid" msgstr "valide" -#: apps/activity/models.py:97 templates/activity/activity_detail.html:56 +#: apps/activity/models.py:107 templates/activity/activity_detail.html:61 msgid "open" msgstr "ouvrir" -#: apps/activity/models.py:102 +#: apps/activity/models.py:112 msgid "activities" msgstr "activités" -#: apps/activity/models.py:114 +#: apps/activity/models.py:125 msgid "entry time" msgstr "heure d'entrée" -#: apps/activity/models.py:137 +#: apps/activity/models.py:148 msgid "Already entered on " msgstr "Déjà rentré le " -#: apps/activity/models.py:137 apps/activity/tables.py:54 +#: apps/activity/models.py:148 apps/activity/tables.py:54 msgid "{:%Y-%m-%d %H:%M:%S}" msgstr "{:%d/%m/%Y %H:%M:%S}" -#: apps/activity/models.py:145 +#: apps/activity/models.py:156 msgid "The balance is negative." msgstr "La note est en négatif." -#: apps/activity/models.py:177 +#: apps/activity/models.py:188 msgid "last name" msgstr "nom de famille" -#: apps/activity/models.py:182 templates/member/profile_info.html:14 +#: apps/activity/models.py:193 templates/member/profile_info.html:14 msgid "first name" msgstr "prénom" -#: apps/activity/models.py:189 +#: apps/activity/models.py:200 msgid "inviter" msgstr "hôte" -#: apps/activity/models.py:202 +#: apps/activity/models.py:234 msgid "guest" msgstr "invité" -#: apps/activity/models.py:203 +#: apps/activity/models.py:235 msgid "guests" msgstr "invités" -#: apps/activity/models.py:214 +#: apps/activity/models.py:247 msgid "Invitation" msgstr "Invitation" @@ -148,7 +165,7 @@ msgstr "Nom de famille" msgid "First name" msgstr "Prénom" -#: apps/activity/tables.py:81 apps/note/models/notes.py:67 +#: apps/activity/tables.py:81 apps/note/models/notes.py:69 msgid "Note" msgstr "Note" @@ -156,11 +173,11 @@ msgstr "Note" msgid "Balance" msgstr "Solde du compte" -#: apps/activity/views.py:35 templates/base.html:94 +#: apps/activity/views.py:44 templates/base.html:94 msgid "Activities" msgstr "Activités" -#: apps/activity/views.py:130 +#: apps/activity/views.py:147 msgid "Entry for activity \"{}\"" msgstr "Entrées pour l'activité « {} »" @@ -172,10 +189,6 @@ msgstr "API" msgid "Logs" msgstr "Logs" -#: apps/logs/models.py:21 apps/note/models/notes.py:117 -msgid "user" -msgstr "utilisateur" - #: apps/logs/models.py:27 msgid "IP Address" msgstr "Adresse IP" @@ -201,7 +214,7 @@ msgid "create" msgstr "Créer" #: apps/logs/models.py:61 apps/note/tables.py:142 -#: templates/activity/activity_detail.html:62 +#: templates/activity/activity_detail.html:67 msgid "edit" msgstr "Modifier" @@ -291,7 +304,8 @@ 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:104 apps/note/models/notes.py:139 +#: apps/member/models.py:104 apps/note/models/notes.py:141 +#: apps/note/models/notes.py:197 msgid "club" msgstr "club" @@ -356,105 +370,105 @@ msgstr "Choisissez une image" msgid "Maximal size: 2MB" msgstr "Taille maximale : 2 Mo" -#: apps/note/models/notes.py:27 +#: apps/note/models/notes.py:29 msgid "account balance" msgstr "solde du compte" -#: apps/note/models/notes.py:28 +#: apps/note/models/notes.py:30 msgid "in centimes, money credited for this instance" msgstr "en centimes, argent crédité pour cette instance" -#: apps/note/models/notes.py:32 +#: apps/note/models/notes.py:34 msgid "last negative date" msgstr "dernier date de négatif" -#: apps/note/models/notes.py:33 +#: apps/note/models/notes.py:35 msgid "last time the balance was negative" msgstr "dernier instant où la note était en négatif" -#: apps/note/models/notes.py:38 +#: apps/note/models/notes.py:40 msgid "active" msgstr "actif" -#: apps/note/models/notes.py:41 +#: apps/note/models/notes.py:43 msgid "" "Designates whether this note should be treated as active. Unselect this " "instead of deleting notes." msgstr "" "Indique si la note est active. Désactiver cela plutôt que supprimer la note." -#: apps/note/models/notes.py:45 +#: apps/note/models/notes.py:47 msgid "display image" msgstr "image affichée" -#: apps/note/models/notes.py:53 apps/note/models/transactions.py:117 +#: apps/note/models/notes.py:55 apps/note/models/transactions.py:117 msgid "created at" msgstr "créée le" -#: apps/note/models/notes.py:59 +#: apps/note/models/notes.py:61 msgid "notes" msgstr "notes" -#: apps/note/models/notes.py:77 apps/note/models/notes.py:101 +#: apps/note/models/notes.py:79 apps/note/models/notes.py:103 msgid "This alias is already taken." msgstr "Cet alias est déjà pris." -#: apps/note/models/notes.py:121 +#: apps/note/models/notes.py:123 msgid "one's note" msgstr "note d'un utilisateur" -#: apps/note/models/notes.py:122 +#: apps/note/models/notes.py:124 msgid "users note" msgstr "notes des utilisateurs" -#: apps/note/models/notes.py:128 +#: apps/note/models/notes.py:130 #, python-format msgid "%(user)s's note" msgstr "Note de %(user)s" -#: apps/note/models/notes.py:143 +#: apps/note/models/notes.py:145 msgid "club note" msgstr "note d'un club" -#: apps/note/models/notes.py:144 +#: apps/note/models/notes.py:146 msgid "clubs notes" msgstr "notes des clubs" -#: apps/note/models/notes.py:150 +#: apps/note/models/notes.py:152 #, python-format msgid "Note of %(club)s club" msgstr "Note du club %(club)s" -#: apps/note/models/notes.py:170 +#: apps/note/models/notes.py:172 msgid "special note" msgstr "note spéciale" -#: apps/note/models/notes.py:171 +#: apps/note/models/notes.py:173 msgid "special notes" msgstr "notes spéciales" -#: apps/note/models/notes.py:194 +#: apps/note/models/notes.py:225 msgid "Invalid alias" msgstr "Alias invalide" -#: apps/note/models/notes.py:210 +#: apps/note/models/notes.py:241 msgid "alias" msgstr "alias" -#: apps/note/models/notes.py:211 templates/member/club_info.html:33 +#: apps/note/models/notes.py:242 templates/member/club_info.html:33 #: templates/member/profile_info.html:36 msgid "aliases" msgstr "alias" -#: apps/note/models/notes.py:233 +#: apps/note/models/notes.py:264 msgid "Alias is too long." msgstr "L'alias est trop long." -#: apps/note/models/notes.py:238 +#: apps/note/models/notes.py:269 msgid "An alias with a similar name already exists: {} " msgstr "Un alias avec un nom similaire existe déjà : {}" -#: apps/note/models/notes.py:251 +#: apps/note/models/notes.py:282 msgid "You can't delete your main alias." msgstr "Vous ne pouvez pas supprimer votre alias principal." @@ -727,31 +741,35 @@ msgstr "" msgid "French" msgstr "" -#: templates/activity/activity_detail.html:45 +#: templates/activity/activity_detail.html:29 +msgid "creater" +msgstr "Créateur" + +#: templates/activity/activity_detail.html:50 msgid "opened" msgstr "ouvert" -#: templates/activity/activity_detail.html:52 +#: templates/activity/activity_detail.html:57 msgid "Entry page" msgstr "Page des entrées" -#: templates/activity/activity_detail.html:56 +#: templates/activity/activity_detail.html:61 msgid "close" msgstr "fermer" -#: templates/activity/activity_detail.html:59 +#: templates/activity/activity_detail.html:64 msgid "invalidate" msgstr "dévalider" -#: templates/activity/activity_detail.html:59 +#: templates/activity/activity_detail.html:64 msgid "validate" msgstr "valider" -#: templates/activity/activity_detail.html:65 +#: templates/activity/activity_detail.html:70 msgid "Invite" msgstr "Inviter" -#: templates/activity/activity_detail.html:72 +#: templates/activity/activity_detail.html:77 msgid "Guests list" msgstr "Liste des invités" @@ -886,7 +904,7 @@ msgstr "Liste des clubs" #: templates/member/club_tables.html:9 msgid "Member of the Club" -msgstr "" +msgstr "Membre du club" #: templates/member/club_tables.html:22 templates/member/profile_tables.html:22 msgid "Transaction history" diff --git a/note_kfet/inputs.py b/note_kfet/inputs.py index e012c1c2..a3170007 100644 --- a/note_kfet/inputs.py +++ b/note_kfet/inputs.py @@ -3,7 +3,7 @@ from json import dumps as json_dumps -from django.forms.widgets import DateTimeBaseInput, NumberInput, Select +from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput class AmountInput(NumberInput): @@ -20,11 +20,11 @@ class AmountInput(NumberInput): return str(int(100 * float(val))) if val else val -class AutocompleteModelSelect(Select): +class Autocomplete(TextInput): template_name = "member/autocomplete_model.html" - def __init__(self, model, attrs=None, choices=()): - super().__init__(attrs, choices) + def __init__(self, model, attrs=None): + super().__init__(attrs) self.model = model self.model_pk = None diff --git a/templates/member/autocomplete_model.html b/templates/member/autocomplete_model.html index c45f13c7..2236c6ef 100644 --- a/templates/member/autocomplete_model.html +++ b/templates/member/autocomplete_model.html @@ -1,5 +1,5 @@ -