mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-30 23:39:54 +01:00 
			
		
		
		
	Guests can't be invited more than 5 times a year and a member can't invite more than 3 people per activity.
This commit is contained in:
		| @@ -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/', | ||||
|   | ||||
| @@ -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): | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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/', | ||||
|   | ||||
| @@ -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/', | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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 <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\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 "" | ||||
|  | ||||
|   | ||||
| @@ -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 <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\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" | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <input type="hidden" name="{{ widget.name }}" {% if widget.attrs.model_pk %}value="{{ widget.attrs.model_pk }}"{% endif %} id="{{ widget.attrs.id }}_pk"> | ||||
| <input class="form-control mx-auto d-block autocomplete" type="text" | ||||
| <input type="text" | ||||
|    {% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %} | ||||
|    name="{{ widget.name }}_name" autocomplete="off" | ||||
|     {% for name, value in widget.attrs.items %} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user