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
# 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/',

View File

@ -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):

View File

@ -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)

View File

@ -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/',

View File

@ -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/',

View File

@ -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.

View File

@ -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 ""

View File

@ -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"

View File

@ -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

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 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 %}