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:
Yohann D'ANELLO 2020-03-30 00:42:32 +02:00
parent 691a03ecad
commit fb5796d35e
10 changed files with 279 additions and 158 deletions

View File

@ -1,11 +1,13 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext as _
from member.models import Club from member.models import Club
from note.models import NoteUser, Note 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 from .models import Activity, Guest
@ -15,18 +17,18 @@ class ActivityForm(forms.ModelForm):
model = Activity model = Activity
exclude = ('creater', 'valid', 'open', ) exclude = ('creater', 'valid', 'open', )
widgets = { widgets = {
"organizer": AutocompleteModelSelect( "organizer": Autocomplete(
model=Club, model=Club,
attrs={"api_url": "/api/members/club/"}, attrs={"api_url": "/api/members/club/"},
), ),
"note": AutocompleteModelSelect( "note": Autocomplete(
model=Note, model=Note,
attrs={ attrs={
"api_url": "/api/note/note/", "api_url": "/api/note/note/",
'placeholder': 'Note de l\'événement sur laquelle envoyer les crédits d\'invitation ...' 'placeholder': 'Note de l\'événement sur laquelle envoyer les crédits d\'invitation ...'
}, },
), ),
"attendees_club": AutocompleteModelSelect( "attendees_club": Autocomplete(
model=Club, model=Club,
attrs={"api_url": "/api/members/club/"}, attrs={"api_url": "/api/members/club/"},
), ),
@ -36,11 +38,34 @@ class ActivityForm(forms.ModelForm):
class GuestForm(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: class Meta:
model = Guest model = Guest
fields = ('last_name', 'first_name', 'inviter', ) fields = ('last_name', 'first_name', 'inviter', )
widgets = { widgets = {
"inviter": AutocompleteModelSelect( "inviter": Autocomplete(
NoteUser, NoteUser,
attrs={ attrs={
'api_url': '/api/note/note/', 'api_url': '/api/note/note/',

View File

@ -1,5 +1,6 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
@ -115,6 +116,7 @@ class Entry(models.Model):
activity = models.ForeignKey( activity = models.ForeignKey(
Activity, Activity,
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name="entries",
verbose_name=_("activity"), verbose_name=_("activity"),
) )
@ -194,7 +196,7 @@ class Guest(models.Model):
inviter = models.ForeignKey( inviter = models.ForeignKey(
NoteUser, NoteUser,
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name='+', related_name='guests',
verbose_name=_("inviter"), verbose_name=_("inviter"),
) )
@ -207,9 +209,31 @@ class Guest(models.Model):
except AttributeError: except AttributeError:
return False 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: class Meta:
verbose_name = _("guest") verbose_name = _("guest")
verbose_name_plural = _("guests") verbose_name_plural = _("guests")
unique_together = ("activity", "last_name", "first_name", )
class GuestTransaction(Transaction): class GuestTransaction(Transaction):

View File

@ -77,6 +77,11 @@ class ActivityInviteView(LoginRequiredMixin, CreateView):
form_class = GuestForm form_class = GuestForm
template_name = "activity/activity_invite.html" 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): def form_valid(self, form):
form.instance.activity = Activity.objects.get(pk=self.kwargs["pk"]) form.instance.activity = Activity.objects.get(pk=self.kwargs["pk"])
return super().form_valid(form) return super().form_valid(form)

View File

@ -7,7 +7,7 @@ from crispy_forms.layout import Layout
from django import forms from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User 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 permission.models import PermissionMask
from .models import Profile, Club, Membership from .models import Profile, Club, Membership
@ -63,7 +63,7 @@ class MembershipForm(forms.ModelForm):
# et récupère les noms d'utilisateur valides # et récupère les noms d'utilisateur valides
widgets = { widgets = {
'user': 'user':
AutocompleteModelSelect( Autocomplete(
User, User,
attrs={ attrs={
'api_url': '/api/user/', 'api_url': '/api/user/',

View File

@ -4,7 +4,7 @@
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _ 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 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} # forward=(forward.Const('TYPE', 'note_type') où TYPE est dans {user, club, special}
widgets = { widgets = {
'destination': 'destination':
AutocompleteModelSelect( Autocomplete(
NoteClub, NoteClub,
attrs={ attrs={
'api_url': '/api/note/note/', 'api_url': '/api/note/note/',

View File

@ -10,6 +10,8 @@ from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
from member.models import Club
""" """
Defines each note types Defines each note types
""" """
@ -174,6 +176,35 @@ class NoteSpecial(Note):
return self.special_type 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): class Alias(models.Model):
""" """
points toward a :model:`note.NoteUser` or :model;`note.NoteClub` instance. points toward a :model:`note.NoteUser` or :model;`note.NoteClub` instance.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,117 +18,134 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/activity/apps.py:10 apps/activity/models.py:101 #: apps/activity/apps.py:10 apps/activity/models.py:111
#: apps/activity/models.py:109 #: apps/activity/models.py:120
msgid "activity" msgid "activity"
msgstr "" 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/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 #: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231
#: templates/member/club_info.html:13 templates/member/profile_info.html:14 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
msgid "name" msgid "name"
msgstr "" 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" msgid "can invite"
msgstr "" 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" msgid "guest entry fee"
msgstr "" msgstr ""
#: apps/activity/models.py:32 #: apps/activity/models.py:34
msgid "activity type" msgid "activity type"
msgstr "" msgstr ""
#: apps/activity/models.py:33 #: apps/activity/models.py:35
msgid "activity types" msgid "activity types"
msgstr "" 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 #: apps/permission/models.py:90 templates/activity/activity_detail.html:16
msgid "description" msgid "description"
msgstr "" 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 #: apps/note/models/transactions.py:62
#: templates/activity/activity_detail.html:19 #: templates/activity/activity_detail.html:19
msgid "type" msgid "type"
msgstr "" 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" msgid "organizer"
msgstr "" msgstr ""
#: apps/activity/models.py:72 apps/activity/models.py:120 apps/note/apps.py:14 #: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14
#: apps/note/models/notes.py:58 #: apps/note/models/notes.py:60
msgid "note" msgid "note"
msgstr "" 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" msgid "attendees club"
msgstr "" 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" msgid "start date"
msgstr "" 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" msgid "end date"
msgstr "" msgstr ""
#: apps/activity/models.py:92 apps/note/models/transactions.py:134 #: apps/activity/models.py:102 apps/note/models/transactions.py:134
#: templates/activity/activity_detail.html:42 #: templates/activity/activity_detail.html:47
msgid "valid" msgid "valid"
msgstr "" 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" msgid "open"
msgstr "" msgstr ""
#: apps/activity/models.py:102 #: apps/activity/models.py:112
msgid "activities" msgid "activities"
msgstr "" msgstr ""
#: apps/activity/models.py:114 #: apps/activity/models.py:125
msgid "entry time" msgid "entry time"
msgstr "" msgstr ""
#: apps/activity/models.py:137 #: apps/activity/models.py:148
msgid "Already entered on " msgid "Already entered on "
msgstr "" 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}" msgid "{:%Y-%m-%d %H:%M:%S}"
msgstr "" msgstr ""
#: apps/activity/models.py:145 #: apps/activity/models.py:156
msgid "The balance is negative." msgid "The balance is negative."
msgstr "" msgstr ""
#: apps/activity/models.py:177 #: apps/activity/models.py:188
msgid "last name" msgid "last name"
msgstr "" 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" msgid "first name"
msgstr "" msgstr ""
#: apps/activity/models.py:189 #: apps/activity/models.py:200
msgid "inviter" msgid "inviter"
msgstr "" msgstr ""
#: apps/activity/models.py:202 #: apps/activity/models.py:234
msgid "guest" msgid "guest"
msgstr "" msgstr ""
#: apps/activity/models.py:203 #: apps/activity/models.py:235
msgid "guests" msgid "guests"
msgstr "" msgstr ""
#: apps/activity/models.py:214 #: apps/activity/models.py:247
msgid "Invitation" msgid "Invitation"
msgstr "" msgstr ""
@ -153,7 +170,7 @@ msgstr ""
msgid "First name" msgid "First name"
msgstr "" 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" msgid "Note"
msgstr "" msgstr ""
@ -161,11 +178,11 @@ msgstr ""
msgid "Balance" msgid "Balance"
msgstr "" msgstr ""
#: apps/activity/views.py:35 templates/base.html:94 #: apps/activity/views.py:44 templates/base.html:94
msgid "Activities" msgid "Activities"
msgstr "" msgstr ""
#: apps/activity/views.py:130 #: apps/activity/views.py:147
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "" msgstr ""
@ -177,10 +194,6 @@ msgstr ""
msgid "Logs" msgid "Logs"
msgstr "" msgstr ""
#: apps/logs/models.py:21 apps/note/models/notes.py:117
msgid "user"
msgstr ""
#: apps/logs/models.py:27 #: apps/logs/models.py:27
msgid "IP Address" msgid "IP Address"
msgstr "" msgstr ""
@ -206,7 +219,7 @@ msgid "create"
msgstr "" msgstr ""
#: apps/logs/models.py:61 apps/note/tables.py:142 #: apps/logs/models.py:61 apps/note/tables.py:142
#: templates/activity/activity_detail.html:62 #: templates/activity/activity_detail.html:67
msgid "edit" msgid "edit"
msgstr "" msgstr ""
@ -292,7 +305,8 @@ msgid ""
"members can renew their membership." "members can renew their membership."
msgstr "" 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" msgid "club"
msgstr "" msgstr ""
@ -357,104 +371,104 @@ msgstr ""
msgid "Maximal size: 2MB" msgid "Maximal size: 2MB"
msgstr "" msgstr ""
#: apps/note/models/notes.py:27 #: apps/note/models/notes.py:29
msgid "account balance" msgid "account balance"
msgstr "" msgstr ""
#: apps/note/models/notes.py:28 #: apps/note/models/notes.py:30
msgid "in centimes, money credited for this instance" msgid "in centimes, money credited for this instance"
msgstr "" msgstr ""
#: apps/note/models/notes.py:32 #: apps/note/models/notes.py:34
msgid "last negative date" msgid "last negative date"
msgstr "" msgstr ""
#: apps/note/models/notes.py:33 #: apps/note/models/notes.py:35
msgid "last time the balance was negative" msgid "last time the balance was negative"
msgstr "" msgstr ""
#: apps/note/models/notes.py:38 #: apps/note/models/notes.py:40
msgid "active" msgid "active"
msgstr "" msgstr ""
#: apps/note/models/notes.py:41 #: apps/note/models/notes.py:43
msgid "" msgid ""
"Designates whether this note should be treated as active. Unselect this " "Designates whether this note should be treated as active. Unselect this "
"instead of deleting notes." "instead of deleting notes."
msgstr "" msgstr ""
#: apps/note/models/notes.py:45 #: apps/note/models/notes.py:47
msgid "display image" msgid "display image"
msgstr "" 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" msgid "created at"
msgstr "" msgstr ""
#: apps/note/models/notes.py:59 #: apps/note/models/notes.py:61
msgid "notes" msgid "notes"
msgstr "" 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." msgid "This alias is already taken."
msgstr "" msgstr ""
#: apps/note/models/notes.py:121 #: apps/note/models/notes.py:123
msgid "one's note" msgid "one's note"
msgstr "" msgstr ""
#: apps/note/models/notes.py:122 #: apps/note/models/notes.py:124
msgid "users note" msgid "users note"
msgstr "" msgstr ""
#: apps/note/models/notes.py:128 #: apps/note/models/notes.py:130
#, python-format #, python-format
msgid "%(user)s's note" msgid "%(user)s's note"
msgstr "" msgstr ""
#: apps/note/models/notes.py:143 #: apps/note/models/notes.py:145
msgid "club note" msgid "club note"
msgstr "" msgstr ""
#: apps/note/models/notes.py:144 #: apps/note/models/notes.py:146
msgid "clubs notes" msgid "clubs notes"
msgstr "" msgstr ""
#: apps/note/models/notes.py:150 #: apps/note/models/notes.py:152
#, python-format #, python-format
msgid "Note of %(club)s club" msgid "Note of %(club)s club"
msgstr "" msgstr ""
#: apps/note/models/notes.py:170 #: apps/note/models/notes.py:172
msgid "special note" msgid "special note"
msgstr "" msgstr ""
#: apps/note/models/notes.py:171 #: apps/note/models/notes.py:173
msgid "special notes" msgid "special notes"
msgstr "" msgstr ""
#: apps/note/models/notes.py:194 #: apps/note/models/notes.py:225
msgid "Invalid alias" msgid "Invalid alias"
msgstr "" msgstr ""
#: apps/note/models/notes.py:210 #: apps/note/models/notes.py:241
msgid "alias" msgid "alias"
msgstr "" 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 #: templates/member/profile_info.html:36
msgid "aliases" msgid "aliases"
msgstr "" msgstr ""
#: apps/note/models/notes.py:233 #: apps/note/models/notes.py:264
msgid "Alias is too long." msgid "Alias is too long."
msgstr "" msgstr ""
#: apps/note/models/notes.py:238 #: apps/note/models/notes.py:269
msgid "An alias with a similar name already exists: {} " msgid "An alias with a similar name already exists: {} "
msgstr "" msgstr ""
#: apps/note/models/notes.py:251 #: apps/note/models/notes.py:282
msgid "You can't delete your main alias." msgid "You can't delete your main alias."
msgstr "" msgstr ""
@ -727,31 +741,35 @@ msgstr ""
msgid "French" msgid "French"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:45 #: templates/activity/activity_detail.html:29
msgid "creater"
msgstr ""
#: templates/activity/activity_detail.html:50
msgid "opened" msgid "opened"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:52 #: templates/activity/activity_detail.html:57
msgid "Entry page" msgid "Entry page"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:56 #: templates/activity/activity_detail.html:61
msgid "close" msgid "close"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:59 #: templates/activity/activity_detail.html:64
msgid "invalidate" msgid "invalidate"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:59 #: templates/activity/activity_detail.html:64
msgid "validate" msgid "validate"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:65 #: templates/activity/activity_detail.html:70
msgid "Invite" msgid "Invite"
msgstr "" msgstr ""
#: templates/activity/activity_detail.html:72 #: templates/activity/activity_detail.html:77
msgid "Guests list" msgid "Guests list"
msgstr "" msgstr ""

View File

@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -13,117 +13,134 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: apps/activity/apps.py:10 apps/activity/models.py:101 #: apps/activity/apps.py:10 apps/activity/models.py:111
#: apps/activity/models.py:109 #: apps/activity/models.py:120
msgid "activity" msgid "activity"
msgstr "activité" 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/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 #: apps/note/models/transactions.py:44 apps/note/models/transactions.py:231
#: templates/member/club_info.html:13 templates/member/profile_info.html:14 #: templates/member/club_info.html:13 templates/member/profile_info.html:14
msgid "name" msgid "name"
msgstr "nom" 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" msgid "can invite"
msgstr "peut inviter" 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" msgid "guest entry fee"
msgstr "cotisation de l'entrée invité" msgstr "cotisation de l'entrée invité"
#: apps/activity/models.py:32 #: apps/activity/models.py:34
msgid "activity type" msgid "activity type"
msgstr "type d'activité" msgstr "type d'activité"
#: apps/activity/models.py:33 #: apps/activity/models.py:35
msgid "activity types" msgid "activity types"
msgstr "types d'activité" 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 #: apps/permission/models.py:90 templates/activity/activity_detail.html:16
msgid "description" msgid "description"
msgstr "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 #: apps/note/models/transactions.py:62
#: templates/activity/activity_detail.html:19 #: templates/activity/activity_detail.html:19
msgid "type" msgid "type"
msgstr "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" msgid "organizer"
msgstr "organisateur" msgstr "organisateur"
#: apps/activity/models.py:72 apps/activity/models.py:120 apps/note/apps.py:14 #: apps/activity/models.py:82 apps/activity/models.py:131 apps/note/apps.py:14
#: apps/note/models/notes.py:58 #: apps/note/models/notes.py:60
msgid "note" msgid "note"
msgstr "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" msgid "attendees club"
msgstr "club attendu" 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" msgid "start date"
msgstr "date de début" 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" msgid "end date"
msgstr "date de fin" msgstr "date de fin"
#: apps/activity/models.py:92 apps/note/models/transactions.py:134 #: apps/activity/models.py:102 apps/note/models/transactions.py:134
#: templates/activity/activity_detail.html:42 #: templates/activity/activity_detail.html:47
msgid "valid" msgid "valid"
msgstr "valide" 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" msgid "open"
msgstr "ouvrir" msgstr "ouvrir"
#: apps/activity/models.py:102 #: apps/activity/models.py:112
msgid "activities" msgid "activities"
msgstr "activités" msgstr "activités"
#: apps/activity/models.py:114 #: apps/activity/models.py:125
msgid "entry time" msgid "entry time"
msgstr "heure d'entrée" msgstr "heure d'entrée"
#: apps/activity/models.py:137 #: apps/activity/models.py:148
msgid "Already entered on " msgid "Already entered on "
msgstr "Déjà rentré le " 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}" msgid "{:%Y-%m-%d %H:%M:%S}"
msgstr "{:%d/%m/%Y %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." msgid "The balance is negative."
msgstr "La note est en négatif." msgstr "La note est en négatif."
#: apps/activity/models.py:177 #: apps/activity/models.py:188
msgid "last name" msgid "last name"
msgstr "nom de famille" 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" msgid "first name"
msgstr "prénom" msgstr "prénom"
#: apps/activity/models.py:189 #: apps/activity/models.py:200
msgid "inviter" msgid "inviter"
msgstr "hôte" msgstr "hôte"
#: apps/activity/models.py:202 #: apps/activity/models.py:234
msgid "guest" msgid "guest"
msgstr "invité" msgstr "invité"
#: apps/activity/models.py:203 #: apps/activity/models.py:235
msgid "guests" msgid "guests"
msgstr "invités" msgstr "invités"
#: apps/activity/models.py:214 #: apps/activity/models.py:247
msgid "Invitation" msgid "Invitation"
msgstr "Invitation" msgstr "Invitation"
@ -148,7 +165,7 @@ msgstr "Nom de famille"
msgid "First name" msgid "First name"
msgstr "Prénom" 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" msgid "Note"
msgstr "Note" msgstr "Note"
@ -156,11 +173,11 @@ msgstr "Note"
msgid "Balance" msgid "Balance"
msgstr "Solde du compte" msgstr "Solde du compte"
#: apps/activity/views.py:35 templates/base.html:94 #: apps/activity/views.py:44 templates/base.html:94
msgid "Activities" msgid "Activities"
msgstr "Activités" msgstr "Activités"
#: apps/activity/views.py:130 #: apps/activity/views.py:147
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "Entrées pour l'activité « {} »" msgstr "Entrées pour l'activité « {} »"
@ -172,10 +189,6 @@ msgstr "API"
msgid "Logs" msgid "Logs"
msgstr "Logs" msgstr "Logs"
#: apps/logs/models.py:21 apps/note/models/notes.py:117
msgid "user"
msgstr "utilisateur"
#: apps/logs/models.py:27 #: apps/logs/models.py:27
msgid "IP Address" msgid "IP Address"
msgstr "Adresse IP" msgstr "Adresse IP"
@ -201,7 +214,7 @@ msgid "create"
msgstr "Créer" msgstr "Créer"
#: apps/logs/models.py:61 apps/note/tables.py:142 #: apps/logs/models.py:61 apps/note/tables.py:142
#: templates/activity/activity_detail.html:62 #: templates/activity/activity_detail.html:67
msgid "edit" msgid "edit"
msgstr "Modifier" msgstr "Modifier"
@ -291,7 +304,8 @@ msgstr ""
"Combien de temps l'adhésion peut durer après le 1er Janvier de l'année " "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." "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" msgid "club"
msgstr "club" msgstr "club"
@ -356,105 +370,105 @@ msgstr "Choisissez une image"
msgid "Maximal size: 2MB" msgid "Maximal size: 2MB"
msgstr "Taille maximale : 2 Mo" msgstr "Taille maximale : 2 Mo"
#: apps/note/models/notes.py:27 #: apps/note/models/notes.py:29
msgid "account balance" msgid "account balance"
msgstr "solde du compte" msgstr "solde du compte"
#: apps/note/models/notes.py:28 #: apps/note/models/notes.py:30
msgid "in centimes, money credited for this instance" msgid "in centimes, money credited for this instance"
msgstr "en centimes, argent crédité pour cette 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" msgid "last negative date"
msgstr "dernier date de négatif" 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" msgid "last time the balance was negative"
msgstr "dernier instant où la note était en négatif" msgstr "dernier instant où la note était en négatif"
#: apps/note/models/notes.py:38 #: apps/note/models/notes.py:40
msgid "active" msgid "active"
msgstr "actif" msgstr "actif"
#: apps/note/models/notes.py:41 #: apps/note/models/notes.py:43
msgid "" msgid ""
"Designates whether this note should be treated as active. Unselect this " "Designates whether this note should be treated as active. Unselect this "
"instead of deleting notes." "instead of deleting notes."
msgstr "" msgstr ""
"Indique si la note est active. Désactiver cela plutôt que supprimer la note." "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" msgid "display image"
msgstr "image affichée" 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" msgid "created at"
msgstr "créée le" msgstr "créée le"
#: apps/note/models/notes.py:59 #: apps/note/models/notes.py:61
msgid "notes" msgid "notes"
msgstr "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." msgid "This alias is already taken."
msgstr "Cet alias est déjà pris." msgstr "Cet alias est déjà pris."
#: apps/note/models/notes.py:121 #: apps/note/models/notes.py:123
msgid "one's note" msgid "one's note"
msgstr "note d'un utilisateur" msgstr "note d'un utilisateur"
#: apps/note/models/notes.py:122 #: apps/note/models/notes.py:124
msgid "users note" msgid "users note"
msgstr "notes des utilisateurs" msgstr "notes des utilisateurs"
#: apps/note/models/notes.py:128 #: apps/note/models/notes.py:130
#, python-format #, python-format
msgid "%(user)s's note" msgid "%(user)s's note"
msgstr "Note de %(user)s" msgstr "Note de %(user)s"
#: apps/note/models/notes.py:143 #: apps/note/models/notes.py:145
msgid "club note" msgid "club note"
msgstr "note d'un club" msgstr "note d'un club"
#: apps/note/models/notes.py:144 #: apps/note/models/notes.py:146
msgid "clubs notes" msgid "clubs notes"
msgstr "notes des clubs" msgstr "notes des clubs"
#: apps/note/models/notes.py:150 #: apps/note/models/notes.py:152
#, python-format #, python-format
msgid "Note of %(club)s club" msgid "Note of %(club)s club"
msgstr "Note du club %(club)s" msgstr "Note du club %(club)s"
#: apps/note/models/notes.py:170 #: apps/note/models/notes.py:172
msgid "special note" msgid "special note"
msgstr "note spéciale" msgstr "note spéciale"
#: apps/note/models/notes.py:171 #: apps/note/models/notes.py:173
msgid "special notes" msgid "special notes"
msgstr "notes spéciales" msgstr "notes spéciales"
#: apps/note/models/notes.py:194 #: apps/note/models/notes.py:225
msgid "Invalid alias" msgid "Invalid alias"
msgstr "Alias invalide" msgstr "Alias invalide"
#: apps/note/models/notes.py:210 #: apps/note/models/notes.py:241
msgid "alias" msgid "alias"
msgstr "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 #: templates/member/profile_info.html:36
msgid "aliases" msgid "aliases"
msgstr "alias" msgstr "alias"
#: apps/note/models/notes.py:233 #: apps/note/models/notes.py:264
msgid "Alias is too long." msgid "Alias is too long."
msgstr "L'alias est trop 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: {} " msgid "An alias with a similar name already exists: {} "
msgstr "Un alias avec un nom similaire existe déjà : {}" 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." msgid "You can't delete your main alias."
msgstr "Vous ne pouvez pas supprimer votre alias principal." msgstr "Vous ne pouvez pas supprimer votre alias principal."
@ -727,31 +741,35 @@ msgstr ""
msgid "French" msgid "French"
msgstr "" 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" msgid "opened"
msgstr "ouvert" msgstr "ouvert"
#: templates/activity/activity_detail.html:52 #: templates/activity/activity_detail.html:57
msgid "Entry page" msgid "Entry page"
msgstr "Page des entrées" msgstr "Page des entrées"
#: templates/activity/activity_detail.html:56 #: templates/activity/activity_detail.html:61
msgid "close" msgid "close"
msgstr "fermer" msgstr "fermer"
#: templates/activity/activity_detail.html:59 #: templates/activity/activity_detail.html:64
msgid "invalidate" msgid "invalidate"
msgstr "dévalider" msgstr "dévalider"
#: templates/activity/activity_detail.html:59 #: templates/activity/activity_detail.html:64
msgid "validate" msgid "validate"
msgstr "valider" msgstr "valider"
#: templates/activity/activity_detail.html:65 #: templates/activity/activity_detail.html:70
msgid "Invite" msgid "Invite"
msgstr "Inviter" msgstr "Inviter"
#: templates/activity/activity_detail.html:72 #: templates/activity/activity_detail.html:77
msgid "Guests list" msgid "Guests list"
msgstr "Liste des invités" msgstr "Liste des invités"
@ -886,7 +904,7 @@ msgstr "Liste des clubs"
#: templates/member/club_tables.html:9 #: templates/member/club_tables.html:9
msgid "Member of the Club" msgid "Member of the Club"
msgstr "" msgstr "Membre du club"
#: templates/member/club_tables.html:22 templates/member/profile_tables.html:22 #: templates/member/club_tables.html:22 templates/member/profile_tables.html:22
msgid "Transaction history" msgid "Transaction history"

View File

@ -3,7 +3,7 @@
from json import dumps as json_dumps 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): class AmountInput(NumberInput):
@ -20,11 +20,11 @@ class AmountInput(NumberInput):
return str(int(100 * float(val))) if val else val return str(int(100 * float(val))) if val else val
class AutocompleteModelSelect(Select): class Autocomplete(TextInput):
template_name = "member/autocomplete_model.html" template_name = "member/autocomplete_model.html"
def __init__(self, model, attrs=None, choices=()): def __init__(self, model, attrs=None):
super().__init__(attrs, choices) super().__init__(attrs)
self.model = model self.model = model
self.model_pk = None self.model_pk = None

View File

@ -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 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 %} {% if widget.value != None and widget.value != "" %}value="{{ widget.value }}"{% endif %}
name="{{ widget.name }}_name" autocomplete="off" name="{{ widget.name }}_name" autocomplete="off"
{% for name, value in widget.attrs.items %} {% for name, value in widget.attrs.items %}