From 82924c999ae8417e1392321e83674959231ada04 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 18:54:21 +0200
Subject: [PATCH 01/23] Add animated profile picture support
---
apps/member/forms.py | 34 +++++++++++++++++++++++++---------
apps/member/views.py | 14 +++++++++++---
2 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/apps/member/forms.py b/apps/member/forms.py
index abefdf2c..04495159 100644
--- a/apps/member/forms.py
+++ b/apps/member/forms.py
@@ -3,7 +3,7 @@
import io
-from PIL import Image
+from PIL import Image, ImageSequence
from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
@@ -82,13 +82,19 @@ class ImageForm(forms.Form):
height = forms.FloatField(widget=forms.HiddenInput())
def clean(self):
- """Load image and crop"""
+ """
+ Load image and crop
+
+ In the future, when Pillow will support APNG we will be able to
+ simplify this code to save only PNG/APNG.
+ """
cleaned_data = super().clean()
# Image size is limited by Django DATA_UPLOAD_MAX_MEMORY_SIZE
image = cleaned_data.get('image')
if image:
# Let Pillow detect and load image
+ # If it is an animation, then there will be multiple frames
try:
im = Image.open(image)
except OSError:
@@ -96,20 +102,30 @@ class ImageForm(forms.Form):
# but Pil is unable to load it
raise forms.ValidationError(_('This image cannot be loaded.'))
- # Crop image
+ # Crop each frame
x = cleaned_data.get('x', 0)
y = cleaned_data.get('y', 0)
w = cleaned_data.get('width', 200)
h = cleaned_data.get('height', 200)
- im = im.crop((x, y, x + w, y + h))
- im = im.resize(
- (settings.PIC_WIDTH, settings.PIC_RATIO * settings.PIC_WIDTH),
- Image.ANTIALIAS,
- )
+ frames = []
+ for frame in ImageSequence.Iterator(im):
+ frame = frame.crop((x, y, x + w, y + h))
+ frame = frame.resize(
+ (settings.PIC_WIDTH, settings.PIC_RATIO * settings.PIC_WIDTH),
+ Image.ANTIALIAS,
+ )
+ frames.append(frame)
# Save
+ om = frames.pop(0) # Get first frame
+ om.info = im.info # Copy metadata
image.file = io.BytesIO()
- im.save(image.file, "PNG")
+ if len(frames) > 1:
+ # Save as GIF
+ om.save(image.file, "GIF", save_all=True, append_images=list(frames), loop=0)
+ else:
+ # Save as PNG
+ om.save(image.file, "PNG")
return cleaned_data
diff --git a/apps/member/views.py b/apps/member/views.py
index 746f5c94..d0ae106a 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -271,9 +271,17 @@ class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, Det
def form_valid(self, form):
"""Save image to note"""
- image_field = form.cleaned_data['image']
- image_field.name = "{}_pic.png".format(self.object.note.pk)
- self.object.note.display_image = image_field
+ image = form.cleaned_data['image']
+
+ # Rename as a PNG or GIF
+ extension = image.name.split(".")[-1]
+ if extension == "gif":
+ image.name = "{}_pic.gif".format(self.object.note.pk)
+ else:
+ image.name = "{}_pic.png".format(self.object.note.pk)
+
+ # Save
+ self.object.note.display_image = image
self.object.note.save()
return super().form_valid(form)
From 40a3405f4708ff3458daa3d3a5726a103df62271 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 19:16:35 +0200
Subject: [PATCH 02/23] Fix missing spaces before comment
---
apps/member/forms.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/member/forms.py b/apps/member/forms.py
index 04495159..9fe8e74c 100644
--- a/apps/member/forms.py
+++ b/apps/member/forms.py
@@ -117,8 +117,8 @@ class ImageForm(forms.Form):
frames.append(frame)
# Save
- om = frames.pop(0) # Get first frame
- om.info = im.info # Copy metadata
+ om = frames.pop(0) # Get first frame
+ om.info = im.info # Copy metadata
image.file = io.BytesIO()
if len(frames) > 1:
# Save as GIF
From cc5996121b4360e07fcf650ee91198c8fa4dbaa5 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 20:04:10 +0200
Subject: [PATCH 03/23] Change HTML localization
---
note_kfet/templates/base.html | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html
index 6d092367..a3b96d45 100644
--- a/note_kfet/templates/base.html
+++ b/note_kfet/templates/base.html
@@ -3,7 +3,8 @@
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
-
+{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
+
From 1023c6c5022f364659082da114df2702b4ea3853 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Sun, 6 Sep 2020 20:18:59 +0200
Subject: [PATCH 04/23] Use pre_delete signal insted of Model.delete() to
prevent note balance issues when deleting a transaction (don't do it) in
Django Admin
---
apps/note/apps.py | 7 ++++++-
apps/note/models/transactions.py | 8 --------
apps/note/signals.py | 8 ++++++++
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/apps/note/apps.py b/apps/note/apps.py
index 4881e3b9..b3dc5a0f 100644
--- a/apps/note/apps.py
+++ b/apps/note/apps.py
@@ -3,7 +3,7 @@
from django.apps import AppConfig
from django.conf import settings
-from django.db.models.signals import post_save
+from django.db.models.signals import post_save, pre_delete
from django.utils.translation import gettext_lazy as _
from . import signals
@@ -25,3 +25,8 @@ class NoteConfig(AppConfig):
signals.save_club_note,
sender='member.Club',
)
+
+ pre_delete.connect(
+ signals.delete_transaction,
+ sender='note.transaction',
+ )
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index a4f220bd..d10bf3a6 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -242,14 +242,6 @@ class Transaction(PolymorphicModel):
self.destination._force_save = True
self.destination.save()
- def delete(self, **kwargs):
- """
- Whenever we want to delete a transaction (caution with this), we ensure the transaction is invalid first.
- """
- self.valid = False
- self.save(**kwargs)
- super().delete(**kwargs)
-
@property
def total(self):
return self.amount * self.quantity
diff --git a/apps/note/signals.py b/apps/note/signals.py
index 06bb480b..51ed92d8 100644
--- a/apps/note/signals.py
+++ b/apps/note/signals.py
@@ -24,3 +24,11 @@ def save_club_note(instance, raw, **_kwargs):
from .models import NoteClub
NoteClub.objects.get_or_create(club=instance)
instance.note.save()
+
+
+def delete_transaction(instance, **_kwargs):
+ """
+ Whenever we want to delete a transaction (caution with this), we ensure the transaction is invalid first.
+ """
+ instance.valid = False
+ instance.save()
From c06354211b55877edd803bfbe5a2897e2638ccea Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 20:21:31 +0200
Subject: [PATCH 05/23] Translate login page
---
apps/member/forms.py | 2 +-
locale/de/LC_MESSAGES/django.po | 162 ++++++++++++++++++--------------
locale/fr/LC_MESSAGES/django.po | 162 ++++++++++++++++++--------------
note_kfet/templates/base.html | 12 +--
4 files changed, 187 insertions(+), 151 deletions(-)
diff --git a/apps/member/forms.py b/apps/member/forms.py
index 9fe8e74c..20de91b7 100644
--- a/apps/member/forms.py
+++ b/apps/member/forms.py
@@ -20,7 +20,7 @@ from .models import Profile, Club, Membership
class CustomAuthenticationForm(AuthenticationForm):
permission_mask = forms.ModelChoiceField(
- label="Masque de permissions",
+ label=_("Permission mask"),
queryset=PermissionMask.objects.order_by("rank"),
empty_label=None,
)
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index b943b130..21c354a8 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-06 12:32+0200\n"
+"POT-Creation-Date: 2020-09-06 20:16+0200\n"
"PO-Revision-Date: 2020-09-03 23:47+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -53,7 +53,7 @@ msgstr "Sie dürfen höchstens 3 Leute zu dieser Veranstaltung einladen."
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:253 apps/note/models/transactions.py:26
-#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:303
+#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:302
#: apps/permission/models.py:329
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118
@@ -244,13 +244,13 @@ msgstr "entfernen"
msgid "Type"
msgstr "Type"
-#: apps/activity/tables.py:82 apps/member/forms.py:167
+#: apps/activity/tables.py:82 apps/member/forms.py:183
#: apps/registration/forms.py:81 apps/treasury/forms.py:129
#: apps/wei/forms/registration.py:96
msgid "Last name"
msgstr "Nachname"
-#: apps/activity/tables.py:84 apps/member/forms.py:172
+#: apps/activity/tables.py:84 apps/member/forms.py:188
#: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:86 apps/treasury/forms.py:131
#: apps/wei/forms/registration.py:101
@@ -270,21 +270,21 @@ msgid "Guests list"
msgstr "Gastliste"
#: apps/activity/templates/activity/activity_entry.html:14
-#: apps/note/models/transactions.py:260
+#: apps/note/models/transactions.py:259
#: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148
-#: note_kfet/templates/base.html:69
+#: note_kfet/templates/base.html:70
msgid "Transfer"
msgstr "Überweisen"
#: apps/activity/templates/activity/activity_entry.html:18
-#: apps/note/models/transactions.py:319
+#: apps/note/models/transactions.py:318
#: apps/note/templates/note/transaction_form.html:21
msgid "Credit"
msgstr "Kredit"
#: apps/activity/templates/activity/activity_entry.html:21
-#: apps/note/models/transactions.py:319
+#: apps/note/models/transactions.py:318
#: apps/note/templates/note/transaction_form.html:25
msgid "Debit"
msgstr "Soll"
@@ -368,7 +368,7 @@ msgstr "Einladen"
msgid "Create new activity"
msgstr "Neue Veranstaltung schaffen"
-#: apps/activity/views.py:63 note_kfet/templates/base.html:87
+#: apps/activity/views.py:63 note_kfet/templates/base.html:88
msgid "Activities"
msgstr "Veranstaltungen"
@@ -480,6 +480,10 @@ msgstr "Preis"
msgid "member"
msgstr "Mitglied"
+#: apps/member/forms.py:23
+msgid "Permission mask"
+msgstr "Berechtigungsmaske"
+
#: apps/member/forms.py:45
msgid "Report frequency"
msgstr "Bericht Frequenz"
@@ -500,53 +504,53 @@ msgstr "Wählen sie ein Bild aus"
msgid "Maximal size: 2MB"
msgstr "Maximal Größe: 2MB"
-#: apps/member/forms.py:97
+#: apps/member/forms.py:103
msgid "This image cannot be loaded."
msgstr "Dieses Bild kann nicht geladen werden."
-#: apps/member/forms.py:123 apps/member/views.py:98
+#: apps/member/forms.py:139 apps/member/views.py:98
#: apps/registration/forms.py:33 apps/registration/views.py:237
msgid "An alias with a similar name already exists."
msgstr "Ein ähnliches Alias ist schon benutzt."
-#: apps/member/forms.py:146 apps/registration/forms.py:61
+#: apps/member/forms.py:162 apps/registration/forms.py:61
msgid "Inscription paid by Société Générale"
msgstr "Mitgliedschaft von der Société Générale bezahlt"
-#: apps/member/forms.py:148 apps/registration/forms.py:63
+#: apps/member/forms.py:164 apps/registration/forms.py:63
msgid "Check this case is the Société Générale paid the inscription."
msgstr "Die Société Générale die Mitgliedschaft bezahlt."
-#: apps/member/forms.py:153 apps/registration/forms.py:68
+#: apps/member/forms.py:169 apps/registration/forms.py:68
#: apps/wei/forms/registration.py:83
msgid "Credit type"
msgstr "Kredittype"
-#: apps/member/forms.py:154 apps/registration/forms.py:69
+#: apps/member/forms.py:170 apps/registration/forms.py:69
#: apps/wei/forms/registration.py:84
msgid "No credit"
msgstr "Kein Kredit"
-#: apps/member/forms.py:156
+#: apps/member/forms.py:172
msgid "You can credit the note of the user."
msgstr "Sie dûrfen diese Note kreditieren."
-#: apps/member/forms.py:160 apps/registration/forms.py:74
+#: apps/member/forms.py:176 apps/registration/forms.py:74
#: apps/wei/forms/registration.py:89
msgid "Credit amount"
msgstr "Kreditanzahl"
-#: apps/member/forms.py:177 apps/note/templates/note/transaction_form.html:140
+#: apps/member/forms.py:193 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:91 apps/treasury/forms.py:133
#: apps/wei/forms/registration.py:106
msgid "Bank"
msgstr "Bank"
-#: apps/member/forms.py:204
+#: apps/member/forms.py:220
msgid "User"
msgstr "User"
-#: apps/member/forms.py:218
+#: apps/member/forms.py:234
msgid "Roles"
msgstr "Rollen"
@@ -790,29 +794,29 @@ msgstr "Mitgliedschaft fängt an"
msgid "membership ends on"
msgstr "Mitgliedschaft endet am"
-#: apps/member/models.py:375
+#: apps/member/models.py:420
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Die Rolle {role} ist nicht erlaubt für das Club {club}."
-#: apps/member/models.py:384 apps/member/views.py:651
+#: apps/member/models.py:429 apps/member/views.py:628
msgid "User is already a member of the club"
msgstr "User ist schon ein Mitglied dieser club"
-#: apps/member/models.py:432
+#: apps/member/models.py:441
msgid "User is not a member of the parent club"
msgstr "User ist noch nicht Mitglied des Urclubs"
-#: apps/member/models.py:480
+#: apps/member/models.py:489
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Mitgliedschaft von {user} für das Club {club}"
-#: apps/member/models.py:483 apps/note/models/transactions.py:360
+#: apps/member/models.py:492 apps/note/models/transactions.py:359
msgid "membership"
msgstr "Mitgliedschaft"
-#: apps/member/models.py:484
+#: apps/member/models.py:493
msgid "memberships"
msgstr "Mitgliedschaften"
@@ -907,7 +911,7 @@ msgstr ""
#: apps/member/templates/member/club_alias.html:10
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:236
-#: apps/member/views.py:425
+#: apps/member/views.py:433
msgid "Note aliases"
msgstr "Note Aliases"
@@ -1058,31 +1062,31 @@ msgstr "User finden"
msgid "Update note picture"
msgstr "Notebild ändern"
-#: apps/member/views.py:293
+#: apps/member/views.py:301
msgid "Manage auth token"
msgstr "Auth token bearbeiten"
-#: apps/member/views.py:320
+#: apps/member/views.py:328
msgid "Create new club"
msgstr "Neue Club"
-#: apps/member/views.py:339
+#: apps/member/views.py:347
msgid "Search club"
msgstr "Club finden"
-#: apps/member/views.py:372
+#: apps/member/views.py:380
msgid "Club detail"
msgstr "Club Details"
-#: apps/member/views.py:448
+#: apps/member/views.py:456
msgid "Update club"
msgstr "Club bearbeiten"
-#: apps/member/views.py:482
+#: apps/member/views.py:490
msgid "Add new member to the club"
msgstr "Neue Mitglieder"
-#: apps/member/views.py:642 apps/wei/views.py:922
+#: apps/member/views.py:619 apps/wei/views.py:922
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@@ -1090,25 +1094,25 @@ msgstr ""
"Diese User hat nicht genug Geld um Mitglied zu werden, und darf nich im Rot "
"sein."
-#: apps/member/views.py:655
+#: apps/member/views.py:632
msgid "The membership must start after {:%m-%d-%Y}."
msgstr "Die Mitgliedschaft muss nach {:%m-%d-Y} anfängen."
-#: apps/member/views.py:660
+#: apps/member/views.py:637
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "Die Mitgliedschaft muss vor {:%m-%d-Y} anfängen."
-#: apps/member/views.py:676 apps/member/views.py:678 apps/member/views.py:680
+#: apps/member/views.py:644 apps/member/views.py:646 apps/member/views.py:648
#: apps/registration/views.py:287 apps/registration/views.py:289
#: apps/registration/views.py:291 apps/wei/views.py:927 apps/wei/views.py:931
msgid "This field is required."
msgstr "Dies ist ein Pflichtfeld."
-#: apps/member/views.py:753
+#: apps/member/views.py:783
msgid "Manage roles of an user in the club"
msgstr "Rollen in diesen Club bearbeiten"
-#: apps/member/views.py:778
+#: apps/member/views.py:808
msgid "Members of the club"
msgstr "Mitlglieder dieses Club"
@@ -1355,34 +1359,34 @@ msgstr ""
"Die Notenguthaben müssen zwischen - 92 233 720 368 547 758,08 € und 92 233 "
"720 368 547 758,07 € liegen."
-#: apps/note/models/transactions.py:280
+#: apps/note/models/transactions.py:279
msgid ""
"The destination of this transaction must equal to the destination of the "
"template."
msgstr ""
"Der Empfänger dieser Transaktion muss dem Empfänger der Vorlage entsprechen."
-#: apps/note/models/transactions.py:289
+#: apps/note/models/transactions.py:288
msgid "Template"
msgstr "Vorlage"
-#: apps/note/models/transactions.py:292
+#: apps/note/models/transactions.py:291
msgid "recurrent transaction"
msgstr "wiederkehrende Transaktion"
-#: apps/note/models/transactions.py:293
+#: apps/note/models/transactions.py:292
msgid "recurrent transactions"
msgstr "wiederkehrende Transaktionen"
-#: apps/note/models/transactions.py:308
+#: apps/note/models/transactions.py:307
msgid "first_name"
msgstr "Vorname"
-#: apps/note/models/transactions.py:313
+#: apps/note/models/transactions.py:312
msgid "bank"
msgstr "Bank"
-#: apps/note/models/transactions.py:330
+#: apps/note/models/transactions.py:329
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
@@ -1390,19 +1394,19 @@ msgstr ""
"Eine Sondertransaktion ist nur zwischen einer Note, die einer "
"Zahlungsmethode zugeordnet ist, und einem User oder einem Club möglich"
-#: apps/note/models/transactions.py:338
+#: apps/note/models/transactions.py:337
msgid "Special transaction"
msgstr "Sondertransaktion"
-#: apps/note/models/transactions.py:339
+#: apps/note/models/transactions.py:338
msgid "Special transactions"
msgstr "Sondertranskationen"
-#: apps/note/models/transactions.py:355
+#: apps/note/models/transactions.py:354
msgid "membership transaction"
msgstr "Mitgliedschafttransaktion"
-#: apps/note/models/transactions.py:356 apps/treasury/models.py:273
+#: apps/note/models/transactions.py:355 apps/treasury/models.py:273
msgid "membership transactions"
msgstr "Mitgliedschaftttransaktionen"
@@ -1574,7 +1578,7 @@ msgstr "Tatsen finden"
msgid "Update button"
msgstr "Tatse bearbeiten"
-#: apps/note/views.py:151 note_kfet/templates/base.html:63
+#: apps/note/views.py:151 note_kfet/templates/base.html:64
msgid "Consumptions"
msgstr "Verbräuche"
@@ -1752,7 +1756,7 @@ msgstr ""
"diesen Parametern zu erstellen. Bitte korrigieren Sie Ihre Daten und "
"versuchen Sie es erneut."
-#: apps/permission/views.py:96 note_kfet/templates/base.html:105
+#: apps/permission/views.py:96 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Rechten"
@@ -1946,7 +1950,7 @@ msgstr ""
msgid "Invalidate pre-registration"
msgstr "Ungültige Vorregistrierung"
-#: apps/treasury/apps.py:12 note_kfet/templates/base.html:93
+#: apps/treasury/apps.py:12 note_kfet/templates/base.html:94
msgid "Treasury"
msgstr "Quaestor"
@@ -2338,7 +2342,7 @@ msgstr "Krediten von der Société générale handeln"
#: apps/wei/apps.py:10 apps/wei/models.py:49 apps/wei/models.py:50
#: apps/wei/models.py:61 apps/wei/models.py:167
-#: note_kfet/templates/base.html:99
+#: note_kfet/templates/base.html:100
msgid "WEI"
msgstr "WEI"
@@ -2942,23 +2946,46 @@ msgstr ""
msgid "Reset"
msgstr "Reset"
-#: note_kfet/templates/base.html:13
+#: note_kfet/templates/base.html:14
msgid "The ENS Paris-Saclay BDE note."
msgstr "Die BDE ENS-Paris-Saclay Note."
-#: note_kfet/templates/base.html:75
+#: note_kfet/templates/base.html:76
msgid "Users"
msgstr "Users"
-#: note_kfet/templates/base.html:81
+#: note_kfet/templates/base.html:82
msgid "Clubs"
msgstr "Clubs"
-#: note_kfet/templates/base.html:110
+#: note_kfet/templates/base.html:111
msgid "Admin"
msgstr "Admin"
-#: note_kfet/templates/base.html:154
+#: note_kfet/templates/base.html:125
+msgid "My account"
+msgstr "Mein Konto"
+
+#: note_kfet/templates/base.html:128
+msgid "Log out"
+msgstr "AAbmelden"
+
+#: note_kfet/templates/base.html:136
+#: note_kfet/templates/registration/signup.html:6
+#: note_kfet/templates/registration/signup.html:11
+#: note_kfet/templates/registration/signup.html:27
+msgid "Sign up"
+msgstr "Registrieren"
+
+#: note_kfet/templates/base.html:143
+#: note_kfet/templates/registration/login.html:6
+#: note_kfet/templates/registration/login.html:15
+#: note_kfet/templates/registration/login.html:38
+#: note_kfet/templates/registration/password_reset_complete.html:15
+msgid "Log in"
+msgstr "Anmelden"
+
+#: note_kfet/templates/base.html:155
msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link."
@@ -2966,6 +2993,10 @@ msgstr ""
"Ihre E-Mail-Adresse ist nicht validiert. Bitte überprüfen Sie Ihren "
"Posteingang und klicken Sie auf den Validierungslink."
+#: note_kfet/templates/base.html:172
+msgid "Contact us"
+msgstr "Kontakt"
+
#: note_kfet/templates/base_search.html:15
msgid "Search by attribute such as name…"
msgstr "Suche nach Attributen wie Name…"
@@ -2998,13 +3029,6 @@ msgstr ""
msgid "Log in again"
msgstr "Nochmal anmelden"
-#: note_kfet/templates/registration/login.html:6
-#: note_kfet/templates/registration/login.html:15
-#: note_kfet/templates/registration/login.html:38
-#: note_kfet/templates/registration/password_reset_complete.html:15
-msgid "Log in"
-msgstr "Anmelden"
-
#: note_kfet/templates/registration/login.html:20
#, python-format
msgid ""
@@ -3096,12 +3120,6 @@ msgstr ""
msgid "Reset my password"
msgstr "Mein Passwort zurücksetzen"
-#: note_kfet/templates/registration/signup.html:6
-#: note_kfet/templates/registration/signup.html:11
-#: note_kfet/templates/registration/signup.html:27
-msgid "Sign up"
-msgstr "Registrieren"
-
#: note_kfet/templates/registration/signup.html:15
msgid ""
"If you already signed up, your registration is taken into account. The BDE "
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 1b715643..353e342a 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-06 12:32+0200\n"
+"POT-Creation-Date: 2020-09-06 20:16+0200\n"
"PO-Revision-Date: 2020-09-02 23:18+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -53,7 +53,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:253 apps/note/models/transactions.py:26
-#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:303
+#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:302
#: apps/permission/models.py:329
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118
@@ -244,13 +244,13 @@ msgstr "supprimer"
msgid "Type"
msgstr "Type"
-#: apps/activity/tables.py:82 apps/member/forms.py:167
+#: apps/activity/tables.py:82 apps/member/forms.py:183
#: apps/registration/forms.py:81 apps/treasury/forms.py:129
#: apps/wei/forms/registration.py:96
msgid "Last name"
msgstr "Nom de famille"
-#: apps/activity/tables.py:84 apps/member/forms.py:172
+#: apps/activity/tables.py:84 apps/member/forms.py:188
#: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:86 apps/treasury/forms.py:131
#: apps/wei/forms/registration.py:101
@@ -270,21 +270,21 @@ msgid "Guests list"
msgstr "Liste des invités"
#: apps/activity/templates/activity/activity_entry.html:14
-#: apps/note/models/transactions.py:260
+#: apps/note/models/transactions.py:259
#: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148
-#: note_kfet/templates/base.html:69
+#: note_kfet/templates/base.html:70
msgid "Transfer"
msgstr "Virement"
#: apps/activity/templates/activity/activity_entry.html:18
-#: apps/note/models/transactions.py:319
+#: apps/note/models/transactions.py:318
#: apps/note/templates/note/transaction_form.html:21
msgid "Credit"
msgstr "Crédit"
#: apps/activity/templates/activity/activity_entry.html:21
-#: apps/note/models/transactions.py:319
+#: apps/note/models/transactions.py:318
#: apps/note/templates/note/transaction_form.html:25
msgid "Debit"
msgstr "Débit"
@@ -368,7 +368,7 @@ msgstr "Inviter"
msgid "Create new activity"
msgstr "Créer une nouvelle activité"
-#: apps/activity/views.py:63 note_kfet/templates/base.html:87
+#: apps/activity/views.py:63 note_kfet/templates/base.html:88
msgid "Activities"
msgstr "Activités"
@@ -482,6 +482,10 @@ msgstr "cotisation"
msgid "member"
msgstr "adhérent"
+#: apps/member/forms.py:23
+msgid "Permission mask"
+msgstr "Masque de permissions"
+
#: apps/member/forms.py:45
msgid "Report frequency"
msgstr "Fréquence des rapports (en jours)"
@@ -502,53 +506,53 @@ msgstr "choisissez une image"
msgid "Maximal size: 2MB"
msgstr "Taille maximale : 2 Mo"
-#: apps/member/forms.py:97
+#: apps/member/forms.py:103
msgid "This image cannot be loaded."
msgstr "Cette image ne peut pas être chargée."
-#: apps/member/forms.py:123 apps/member/views.py:98
+#: apps/member/forms.py:139 apps/member/views.py:98
#: apps/registration/forms.py:33 apps/registration/views.py:237
msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà."
-#: apps/member/forms.py:146 apps/registration/forms.py:61
+#: apps/member/forms.py:162 apps/registration/forms.py:61
msgid "Inscription paid by Société Générale"
msgstr "Inscription payée par la Société générale"
-#: apps/member/forms.py:148 apps/registration/forms.py:63
+#: apps/member/forms.py:164 apps/registration/forms.py:63
msgid "Check this case is the Société Générale paid the inscription."
msgstr "Cochez cette case si la Société Générale a payé l'inscription."
-#: apps/member/forms.py:153 apps/registration/forms.py:68
+#: apps/member/forms.py:169 apps/registration/forms.py:68
#: apps/wei/forms/registration.py:83
msgid "Credit type"
msgstr "Type de rechargement"
-#: apps/member/forms.py:154 apps/registration/forms.py:69
+#: apps/member/forms.py:170 apps/registration/forms.py:69
#: apps/wei/forms/registration.py:84
msgid "No credit"
msgstr "Pas de rechargement"
-#: apps/member/forms.py:156
+#: apps/member/forms.py:172
msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion."
-#: apps/member/forms.py:160 apps/registration/forms.py:74
+#: apps/member/forms.py:176 apps/registration/forms.py:74
#: apps/wei/forms/registration.py:89
msgid "Credit amount"
msgstr "Montant à créditer"
-#: apps/member/forms.py:177 apps/note/templates/note/transaction_form.html:140
+#: apps/member/forms.py:193 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:91 apps/treasury/forms.py:133
#: apps/wei/forms/registration.py:106
msgid "Bank"
msgstr "Banque"
-#: apps/member/forms.py:204
+#: apps/member/forms.py:220
msgid "User"
msgstr "Utilisateur"
-#: apps/member/forms.py:218
+#: apps/member/forms.py:234
msgid "Roles"
msgstr "Rôles"
@@ -792,29 +796,29 @@ msgstr "l'adhésion commence le"
msgid "membership ends on"
msgstr "l'adhésion finit le"
-#: apps/member/models.py:375
+#: apps/member/models.py:420
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
-#: apps/member/models.py:384 apps/member/views.py:651
+#: apps/member/models.py:429 apps/member/views.py:628
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
-#: apps/member/models.py:432
+#: apps/member/models.py:441
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
-#: apps/member/models.py:480
+#: apps/member/models.py:489
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}"
-#: apps/member/models.py:483 apps/note/models/transactions.py:360
+#: apps/member/models.py:492 apps/note/models/transactions.py:359
msgid "membership"
msgstr "adhésion"
-#: apps/member/models.py:484
+#: apps/member/models.py:493
msgid "memberships"
msgstr "adhésions"
@@ -909,7 +913,7 @@ msgstr ""
#: apps/member/templates/member/club_alias.html:10
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:236
-#: apps/member/views.py:425
+#: apps/member/views.py:433
msgid "Note aliases"
msgstr "Alias de la note"
@@ -1060,31 +1064,31 @@ msgstr "Chercher un utilisateur"
msgid "Update note picture"
msgstr "Modifier la photo de la note"
-#: apps/member/views.py:293
+#: apps/member/views.py:301
msgid "Manage auth token"
msgstr "Gérer les jetons d'authentification"
-#: apps/member/views.py:320
+#: apps/member/views.py:328
msgid "Create new club"
msgstr "Créer un nouveau club"
-#: apps/member/views.py:339
+#: apps/member/views.py:347
msgid "Search club"
msgstr "Chercher un club"
-#: apps/member/views.py:372
+#: apps/member/views.py:380
msgid "Club detail"
msgstr "Détails du club"
-#: apps/member/views.py:448
+#: apps/member/views.py:456
msgid "Update club"
msgstr "Modifier le club"
-#: apps/member/views.py:482
+#: apps/member/views.py:490
msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club"
-#: apps/member/views.py:642 apps/wei/views.py:922
+#: apps/member/views.py:619 apps/wei/views.py:922
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@@ -1092,25 +1096,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif."
-#: apps/member/views.py:655
+#: apps/member/views.py:632
msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
-#: apps/member/views.py:660
+#: apps/member/views.py:637
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
-#: apps/member/views.py:676 apps/member/views.py:678 apps/member/views.py:680
+#: apps/member/views.py:644 apps/member/views.py:646 apps/member/views.py:648
#: apps/registration/views.py:287 apps/registration/views.py:289
#: apps/registration/views.py:291 apps/wei/views.py:927 apps/wei/views.py:931
msgid "This field is required."
msgstr "Ce champ est requis."
-#: apps/member/views.py:753
+#: apps/member/views.py:783
msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club"
-#: apps/member/views.py:778
+#: apps/member/views.py:808
msgid "Members of the club"
msgstr "Membres du club"
@@ -1359,7 +1363,7 @@ msgstr ""
"€ et 92 233 720 368 547 758.07 €. Ne cherchez pas à capitaliser l'argent du "
"BDE."
-#: apps/note/models/transactions.py:280
+#: apps/note/models/transactions.py:279
msgid ""
"The destination of this transaction must equal to the destination of the "
"template."
@@ -1367,27 +1371,27 @@ msgstr ""
"Le destinataire de cette transaction doit être identique à celui du bouton "
"utilisé."
-#: apps/note/models/transactions.py:289
+#: apps/note/models/transactions.py:288
msgid "Template"
msgstr "Bouton"
-#: apps/note/models/transactions.py:292
+#: apps/note/models/transactions.py:291
msgid "recurrent transaction"
msgstr "transaction issue de bouton"
-#: apps/note/models/transactions.py:293
+#: apps/note/models/transactions.py:292
msgid "recurrent transactions"
msgstr "transactions issues de boutons"
-#: apps/note/models/transactions.py:308
+#: apps/note/models/transactions.py:307
msgid "first_name"
msgstr "prénom"
-#: apps/note/models/transactions.py:313
+#: apps/note/models/transactions.py:312
msgid "bank"
msgstr "banque"
-#: apps/note/models/transactions.py:330
+#: apps/note/models/transactions.py:329
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
@@ -1395,19 +1399,19 @@ msgstr ""
"Une transaction spéciale n'est possible que entre une note associée à un "
"mode de paiement et un utilisateur ou un club"
-#: apps/note/models/transactions.py:338
+#: apps/note/models/transactions.py:337
msgid "Special transaction"
msgstr "Transaction de crédit/retrait"
-#: apps/note/models/transactions.py:339
+#: apps/note/models/transactions.py:338
msgid "Special transactions"
msgstr "Transactions de crédit/retrait"
-#: apps/note/models/transactions.py:355
+#: apps/note/models/transactions.py:354
msgid "membership transaction"
msgstr "transaction d'adhésion"
-#: apps/note/models/transactions.py:356 apps/treasury/models.py:273
+#: apps/note/models/transactions.py:355 apps/treasury/models.py:273
msgid "membership transactions"
msgstr "transactions d'adhésion"
@@ -1579,7 +1583,7 @@ msgstr "Chercher un bouton"
msgid "Update button"
msgstr "Modifier le bouton"
-#: apps/note/views.py:151 note_kfet/templates/base.html:63
+#: apps/note/views.py:151 note_kfet/templates/base.html:64
msgid "Consumptions"
msgstr "Consommations"
@@ -1758,7 +1762,7 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » "
"avec ces paramètres. Merci de les corriger et de réessayer."
-#: apps/permission/views.py:96 note_kfet/templates/base.html:105
+#: apps/permission/views.py:96 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Droits"
@@ -1950,7 +1954,7 @@ msgstr ""
msgid "Invalidate pre-registration"
msgstr "Invalider l'inscription"
-#: apps/treasury/apps.py:12 note_kfet/templates/base.html:93
+#: apps/treasury/apps.py:12 note_kfet/templates/base.html:94
msgid "Treasury"
msgstr "Trésorerie"
@@ -2340,7 +2344,7 @@ msgstr "Gérer les crédits de la Société générale"
#: apps/wei/apps.py:10 apps/wei/models.py:49 apps/wei/models.py:50
#: apps/wei/models.py:61 apps/wei/models.py:167
-#: note_kfet/templates/base.html:99
+#: note_kfet/templates/base.html:100
msgid "WEI"
msgstr "WEI"
@@ -2944,23 +2948,46 @@ msgstr ""
msgid "Reset"
msgstr "Réinitialiser"
-#: note_kfet/templates/base.html:13
+#: note_kfet/templates/base.html:14
msgid "The ENS Paris-Saclay BDE note."
msgstr "La note du BDE de l'ENS Paris-Saclay."
-#: note_kfet/templates/base.html:75
+#: note_kfet/templates/base.html:76
msgid "Users"
msgstr "Utilisateurs"
-#: note_kfet/templates/base.html:81
+#: note_kfet/templates/base.html:82
msgid "Clubs"
msgstr "Clubs"
-#: note_kfet/templates/base.html:110
+#: note_kfet/templates/base.html:111
msgid "Admin"
msgstr "Admin"
-#: note_kfet/templates/base.html:154
+#: note_kfet/templates/base.html:125
+msgid "My account"
+msgstr "Mon compte"
+
+#: note_kfet/templates/base.html:128
+msgid "Log out"
+msgstr "Se déconnecter"
+
+#: note_kfet/templates/base.html:136
+#: note_kfet/templates/registration/signup.html:6
+#: note_kfet/templates/registration/signup.html:11
+#: note_kfet/templates/registration/signup.html:27
+msgid "Sign up"
+msgstr "Inscription"
+
+#: note_kfet/templates/base.html:143
+#: note_kfet/templates/registration/login.html:6
+#: note_kfet/templates/registration/login.html:15
+#: note_kfet/templates/registration/login.html:38
+#: note_kfet/templates/registration/password_reset_complete.html:15
+msgid "Log in"
+msgstr "Se connecter"
+
+#: note_kfet/templates/base.html:155
msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link."
@@ -2968,6 +2995,10 @@ msgstr ""
"Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail "
"et de cliquer sur le lien de validation."
+#: note_kfet/templates/base.html:172
+msgid "Contact us"
+msgstr "Nous contacter"
+
#: note_kfet/templates/base_search.html:15
msgid "Search by attribute such as name…"
msgstr "Chercher par un attribut tel que le nom …"
@@ -2999,13 +3030,6 @@ msgstr "Merci d'avoir utilisé la Note Kfet."
msgid "Log in again"
msgstr "Se connecter à nouveau"
-#: note_kfet/templates/registration/login.html:6
-#: note_kfet/templates/registration/login.html:15
-#: note_kfet/templates/registration/login.html:38
-#: note_kfet/templates/registration/password_reset_complete.html:15
-msgid "Log in"
-msgstr "Se connecter"
-
#: note_kfet/templates/registration/login.html:20
#, python-format
msgid ""
@@ -3097,12 +3121,6 @@ msgstr ""
msgid "Reset my password"
msgstr "Réinitialiser mon mot de passe"
-#: note_kfet/templates/registration/signup.html:6
-#: note_kfet/templates/registration/signup.html:11
-#: note_kfet/templates/registration/signup.html:27
-msgid "Sign up"
-msgstr "Inscription"
-
#: note_kfet/templates/registration/signup.html:15
msgid ""
"If you already signed up, your registration is taken into account. The BDE "
diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html
index a3b96d45..7cd8fbc8 100644
--- a/note_kfet/templates/base.html
+++ b/note_kfet/templates/base.html
@@ -38,7 +38,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
- {# Si un formulaire requiert des données supplémentaires (notamment JS), les données sont chargées #}
+ {# If extra ressources are needed for a form, load here #}
{% if form.media %}
{{ form.media }}
{% endif %}
@@ -122,10 +122,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
@@ -133,14 +133,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% if request.path != "/registration/signup/" %}
- S'inscrire
+ {% trans "Sign up" %}
{% endif %}
{% if request.path != "/accounts/login/" %}
- Se connecter
+ {% trans "Log in" %}
{% endif %}
@@ -169,7 +169,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
class="form-inline">
Nous contacter —
+ class="text-muted">{% trans "Contact us" %} —
{% csrf_token %}
Date: Sun, 6 Sep 2020 20:25:12 +0200
Subject: [PATCH 06/23] Tippfehler
---
locale/de/LC_MESSAGES/django.po | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 21c354a8..674e5ce0 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -2968,7 +2968,7 @@ msgstr "Mein Konto"
#: note_kfet/templates/base.html:128
msgid "Log out"
-msgstr "AAbmelden"
+msgstr "Abmelden"
#: note_kfet/templates/base.html:136
#: note_kfet/templates/registration/signup.html:6
From 012b84614c8690243294fd5c10b37368766841f7 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 20:32:46 +0200
Subject: [PATCH 07/23] Hide asterix on login form
---
apps/registration/static/registration/css/login.css | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/apps/registration/static/registration/css/login.css b/apps/registration/static/registration/css/login.css
index b789b2f7..b1bac970 100644
--- a/apps/registration/static/registration/css/login.css
+++ b/apps/registration/static/registration/css/login.css
@@ -16,4 +16,8 @@ Font-Awesome attribution is already done inside SVG files
#login-form select {
-moz-appearance: none;
cursor: pointer;
-}
\ No newline at end of file
+}
+
+#login-form .asteriskField {
+ display: none;
+}
From b6901ea1e535cdf5140efa19a79ea2be373e6734 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 20:49:06 +0200
Subject: [PATCH 08/23] Use flake8-django
---
tox.ini | 1 +
1 file changed, 1 insertion(+)
diff --git a/tox.ini b/tox.ini
index 1b0f4b55..1c32a412 100644
--- a/tox.ini
+++ b/tox.ini
@@ -22,6 +22,7 @@ commands =
deps =
flake8
flake8-colors
+ flake8-django
flake8-import-order
flake8-typing-imports
pep8-naming
From 48407cacf8aee2f42aacbbb01b951d8a598d12af Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 21:19:17 +0200
Subject: [PATCH 09/23] Call subprocesses with absolute path
---
apps/treasury/views.py | 2 +-
apps/wei/tests/test_wei_registration.py | 2 +-
apps/wei/views.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/treasury/views.py b/apps/treasury/views.py
index 7e9ecc51..a8e03cbe 100644
--- a/apps/treasury/views.py
+++ b/apps/treasury/views.py
@@ -209,7 +209,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
# The file has to be rendered twice
for ignored in range(2):
error = subprocess.Popen(
- ["xelatex", "-interaction=nonstopmode", "invoice-{}.tex".format(pk)],
+ ["/usr/bin/xelatex", "-interaction=nonstopmode", "invoice-{}.tex".format(pk)],
cwd=tmp_dir,
stdin=open(os.devnull, "r"),
stderr=open(os.devnull, "wb"),
diff --git a/apps/wei/tests/test_wei_registration.py b/apps/wei/tests/test_wei_registration.py
index e1724419..6d294bdd 100644
--- a/apps/wei/tests/test_wei_registration.py
+++ b/apps/wei/tests/test_wei_registration.py
@@ -690,7 +690,7 @@ class TestWEIRegistration(TestCase):
"""
with open("/dev/null", "wb") as devnull:
return subprocess.call(
- ["which", "xelatex"],
+ ["/usr/bin/which", "xelatex"],
stdout=devnull,
stderr=devnull,
) == 0
diff --git a/apps/wei/views.py b/apps/wei/views.py
index ced85473..8246bebf 100644
--- a/apps/wei/views.py
+++ b/apps/wei/views.py
@@ -1103,7 +1103,7 @@ class MemberListRenderView(LoginRequiredMixin, View):
with open(os.devnull, "wb") as devnull:
error = subprocess.Popen(
- ["xelatex", "-interaction=nonstopmode", "{}/wei-list.tex".format(tmp_dir)],
+ ["/usr/bin/xelatex", "-interaction=nonstopmode", "{}/wei-list.tex".format(tmp_dir)],
cwd=tmp_dir,
stderr=devnull,
stdout=devnull,
From 89b2ff52e3d591a1b83d8edced3a99570e04a793 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 21:38:55 +0200
Subject: [PATCH 10/23] Fix I'm the emitter button
---
apps/note/templates/note/transaction_form.html | 4 ++--
apps/permission/tests/test_permission_queries.py | 1 -
note_kfet/static/js/transfer.js | 5 ++++-
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/apps/note/templates/note/transaction_form.html b/apps/note/templates/note/transaction_form.html
index 9c484799..3f58b793 100644
--- a/apps/note/templates/note/transaction_form.html
+++ b/apps/note/templates/note/transaction_form.html
@@ -65,9 +65,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
diff --git a/apps/permission/tests/test_permission_queries.py b/apps/permission/tests/test_permission_queries.py
index 4d73ae11..fdd530a5 100644
--- a/apps/permission/tests/test_permission_queries.py
+++ b/apps/permission/tests/test_permission_queries.py
@@ -78,7 +78,6 @@ class PermissionQueryTestCase(TestCase):
query = instanced.query
model = perm.model.model_class()
model.objects.filter(query).all()
- # print("Good query for permission", perm)
except (FieldError, AttributeError, ValueError, TypeError, JSONDecodeError):
print("Query error for permission", perm)
print("Query:", perm.query)
diff --git a/note_kfet/static/js/transfer.js b/note_kfet/static/js/transfer.js
index db9cf9ac..94190da5 100644
--- a/note_kfet/static/js/transfer.js
+++ b/note_kfet/static/js/transfer.js
@@ -183,7 +183,10 @@ $(document).ready(function () {
if (location.hash) { $('#type_' + location.hash.substr(1)).click() } else { type_transfer.click() }
- $('#source_me').click(function () {
+ $('#source_me').click(function (event) {
+ // Prevent TurboLinks
+ event.preventDefault();
+
if (LOCK) { return }
// Shortcut to set the current user as the only emitter
From 27aa2e9da8c6293dde5130e132764333cca4636b Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 21:41:33 +0200
Subject: [PATCH 11/23] JQuery is unable to cancel Turbolinks
---
apps/note/templates/note/transaction_form.html | 2 +-
note_kfet/static/js/transfer.js | 5 +----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/apps/note/templates/note/transaction_form.html b/apps/note/templates/note/transaction_form.html
index 3f58b793..f5ff0b73 100644
--- a/apps/note/templates/note/transaction_form.html
+++ b/apps/note/templates/note/transaction_form.html
@@ -65,7 +65,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
diff --git a/note_kfet/static/js/transfer.js b/note_kfet/static/js/transfer.js
index 94190da5..db9cf9ac 100644
--- a/note_kfet/static/js/transfer.js
+++ b/note_kfet/static/js/transfer.js
@@ -183,10 +183,7 @@ $(document).ready(function () {
if (location.hash) { $('#type_' + location.hash.substr(1)).click() } else { type_transfer.click() }
- $('#source_me').click(function (event) {
- // Prevent TurboLinks
- event.preventDefault();
-
+ $('#source_me').click(function () {
if (LOCK) { return }
// Shortcut to set the current user as the only emitter
From 4452d112e3bd7a0aba9e028505c171e11a302907 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Sun, 6 Sep 2020 21:50:06 +0200
Subject: [PATCH 12/23] Navbar should expand only on large screen
---
note_kfet/templates/base.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/note_kfet/templates/base.html b/note_kfet/templates/base.html
index 7cd8fbc8..f65fe87c 100644
--- a/note_kfet/templates/base.html
+++ b/note_kfet/templates/base.html
@@ -47,7 +47,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
-
+
{{ request.site.name }}
Date: Sun, 6 Sep 2020 21:54:12 +0200
Subject: [PATCH 13/23] Fix alias count on club info
---
apps/member/templates/member/includes/club_info.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/member/templates/member/includes/club_info.html b/apps/member/templates/member/includes/club_info.html
index 92c7b569..51f0ef03 100644
--- a/apps/member/templates/member/includes/club_info.html
+++ b/apps/member/templates/member/includes/club_info.html
@@ -48,10 +48,10 @@
- {% trans 'Manage aliases' %} ({{ user_object.note.alias_set.all|length }})
+ {% trans 'Manage aliases' %} ({{ club.note.alias_set.all|length }})
{% trans 'email'|capfirst %}
{{ club.email }}
-
\ No newline at end of file
+
From 53c4e3877150bb3bc8796d20296e273155f78cad Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 01:06:22 +0200
Subject: [PATCH 14/23] Add __str__ to models, remove null=True in CharField
and TextField
---
apps/activity/models.py | 6 ++++
.../migrations/0002_replace_null_by_blank.py | 17 +++++++++++
.../0003_remove_null_tag_on_charfields.py | 23 +++++++++++++++
apps/logs/models.py | 10 +++++--
apps/logs/signals.py | 4 +--
.../migrations/0004_replace_null_by_blank.py | 20 +++++++++++++
.../0005_remove_null_tag_on_charfields.py | 28 +++++++++++++++++++
apps/member/models.py | 9 +++---
.../migrations/0003_replace_null_by_blank.py | 17 +++++++++++
.../0004_remove_null_tag_on_charfields.py | 23 +++++++++++++++
apps/note/models/notes.py | 4 +--
apps/note/models/transactions.py | 8 ++++--
apps/scripts | 2 +-
apps/treasury/models.py | 12 ++++++++
14 files changed, 168 insertions(+), 15 deletions(-)
create mode 100644 apps/logs/migrations/0002_replace_null_by_blank.py
create mode 100644 apps/logs/migrations/0003_remove_null_tag_on_charfields.py
create mode 100644 apps/member/migrations/0004_replace_null_by_blank.py
create mode 100644 apps/member/migrations/0005_remove_null_tag_on_charfields.py
create mode 100644 apps/note/migrations/0003_replace_null_by_blank.py
create mode 100644 apps/note/migrations/0004_remove_null_tag_on_charfields.py
diff --git a/apps/activity/models.py b/apps/activity/models.py
index 9d3431be..fe2cfb20 100644
--- a/apps/activity/models.py
+++ b/apps/activity/models.py
@@ -188,6 +188,12 @@ class Entry(models.Model):
verbose_name = _("entry")
verbose_name_plural = _("entries")
+ def __str__(self):
+ return _("Entry for {guest}, invited by {note} to the activity {activity}").format(
+ guest=str(self.guest), note=str(self.note), activity=str(self.activity)) if self.guest \
+ else _("Entry for {note} to the activity {activity}").format(
+ guest=str(self.guest), note=str(self.note), activity=str(self.activity))
+
def save(self, *args, **kwargs):
qs = Entry.objects.filter(~Q(pk=self.pk), activity=self.activity, note=self.note, guest=self.guest)
diff --git a/apps/logs/migrations/0002_replace_null_by_blank.py b/apps/logs/migrations/0002_replace_null_by_blank.py
new file mode 100644
index 00000000..65fc4b14
--- /dev/null
+++ b/apps/logs/migrations/0002_replace_null_by_blank.py
@@ -0,0 +1,17 @@
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('logs', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RunSQL(
+ "UPDATE logs_changelog SET previous = '' WHERE previous IS NULL;"
+ ),
+ migrations.RunSQL(
+ "UPDATE logs_changelog SET data = '' WHERE data IS NULL;"
+ ),
+ ]
diff --git a/apps/logs/migrations/0003_remove_null_tag_on_charfields.py b/apps/logs/migrations/0003_remove_null_tag_on_charfields.py
new file mode 100644
index 00000000..a6e3a581
--- /dev/null
+++ b/apps/logs/migrations/0003_remove_null_tag_on_charfields.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.16 on 2020-09-06 19:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('logs', '0002_replace_null_by_blank'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='changelog',
+ name='data',
+ field=models.TextField(blank=True, default='', verbose_name='new data'),
+ ),
+ migrations.AlterField(
+ model_name='changelog',
+ name='previous',
+ field=models.TextField(blank=True, default='', verbose_name='previous data'),
+ ),
+ ]
diff --git a/apps/logs/models.py b/apps/logs/models.py
index e558ea82..0077af72 100644
--- a/apps/logs/models.py
+++ b/apps/logs/models.py
@@ -44,12 +44,14 @@ class Changelog(models.Model):
)
previous = models.TextField(
- null=True,
+ blank=True,
+ default="",
verbose_name=_('previous data'),
)
data = models.TextField(
- null=True,
+ blank=True,
+ default="",
verbose_name=_('new data'),
)
@@ -80,3 +82,7 @@ class Changelog(models.Model):
class Meta:
verbose_name = _("changelog")
verbose_name_plural = _("changelogs")
+
+ def __str__(self):
+ return _("Changelog of type \"{action}\" for model {model} at {timestamp}").format(
+ action=self.get_action_display(), model=str(self.model), timestamp=str(self.timestamp))
diff --git a/apps/logs/signals.py b/apps/logs/signals.py
index e58ba7c1..f313cc5b 100644
--- a/apps/logs/signals.py
+++ b/apps/logs/signals.py
@@ -99,7 +99,7 @@ def save_object(sender, instance, **kwargs):
model = instance.__class__
fields = changed_fields
- previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8") if previous else None
+ previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8") if previous else ""
instance_json = JSONRenderer().render(CustomSerializer(instance).data).decode("UTF-8")
Changelog.objects.create(user=user,
@@ -149,6 +149,6 @@ def delete_object(sender, instance, **kwargs):
model=ContentType.objects.get_for_model(instance),
instance_pk=instance.pk,
previous=instance_json,
- data=None,
+ data="",
action="delete"
).save()
diff --git a/apps/member/migrations/0004_replace_null_by_blank.py b/apps/member/migrations/0004_replace_null_by_blank.py
new file mode 100644
index 00000000..a53e3801
--- /dev/null
+++ b/apps/member/migrations/0004_replace_null_by_blank.py
@@ -0,0 +1,20 @@
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('member', '0003_create_bde_and_kfet'),
+ ]
+
+ operations = [
+ migrations.RunSQL(
+ "UPDATE member_profile SET address = '' WHERE address IS NULL;",
+ ),
+ migrations.RunSQL(
+ "UPDATE member_profile SET ml_events_registration = '' WHERE ml_events_registration IS NULL;",
+ ),
+ migrations.RunSQL(
+ "UPDATE member_profile SET section = '' WHERE section IS NULL;",
+ ),
+ ]
diff --git a/apps/member/migrations/0005_remove_null_tag_on_charfields.py b/apps/member/migrations/0005_remove_null_tag_on_charfields.py
new file mode 100644
index 00000000..11b9f37b
--- /dev/null
+++ b/apps/member/migrations/0005_remove_null_tag_on_charfields.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.2.16 on 2020-09-06 19:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('member', '0004_replace_null_by_blank'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='profile',
+ name='address',
+ field=models.CharField(blank=True, default='', max_length=255, verbose_name='address'),
+ ),
+ migrations.AlterField(
+ model_name='profile',
+ name='ml_events_registration',
+ field=models.CharField(blank=True, choices=[('', 'No'), ('fr', 'Yes (receive them in french)'), ('en', 'Yes (receive them in english)')], default='', max_length=2, verbose_name='Register on the mailing list to stay informed of the events of the campus (1 mail/week)'),
+ ),
+ migrations.AlterField(
+ model_name='profile',
+ name='section',
+ field=models.CharField(blank=True, default='', help_text='e.g. "1A0", "9A♥", "SAPHIRE"', max_length=255, verbose_name='section'),
+ ),
+ ]
diff --git a/apps/member/models.py b/apps/member/models.py
index bce525af..c7467120 100644
--- a/apps/member/models.py
+++ b/apps/member/models.py
@@ -46,7 +46,7 @@ class Profile(models.Model):
help_text=_('e.g. "1A0", "9A♥", "SAPHIRE"'),
max_length=255,
blank=True,
- null=True,
+ default="",
)
department = models.CharField(
@@ -83,7 +83,7 @@ class Profile(models.Model):
verbose_name=_('address'),
max_length=255,
blank=True,
- null=True,
+ default="",
)
paid = models.BooleanField(
@@ -94,11 +94,10 @@ class Profile(models.Model):
ml_events_registration = models.CharField(
blank=True,
- null=True,
- default=None,
+ default='',
max_length=2,
choices=[
- (None, _("No")),
+ ('', _("No")),
('fr', _("Yes (receive them in french)")),
('en', _("Yes (receive them in english)")),
],
diff --git a/apps/note/migrations/0003_replace_null_by_blank.py b/apps/note/migrations/0003_replace_null_by_blank.py
new file mode 100644
index 00000000..21da860d
--- /dev/null
+++ b/apps/note/migrations/0003_replace_null_by_blank.py
@@ -0,0 +1,17 @@
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('note', '0002_create_special_notes'),
+ ]
+
+ operations = [
+ migrations.RunSQL(
+ "UPDATE note_note SET inactivity_reason = '' WHERE inactivity_reason IS NULL;"
+ ),
+ migrations.RunSQL(
+ "UPDATE note_transaction SET invalidity_reason = '' WHERE invalidity_reason IS NULL;"
+ ),
+ ]
diff --git a/apps/note/migrations/0004_remove_null_tag_on_charfields.py b/apps/note/migrations/0004_remove_null_tag_on_charfields.py
new file mode 100644
index 00000000..012fc359
--- /dev/null
+++ b/apps/note/migrations/0004_remove_null_tag_on_charfields.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.16 on 2020-09-06 19:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('note', '0003_replace_null_by_blank'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='note',
+ name='inactivity_reason',
+ field=models.CharField(blank=True, choices=[('manual', 'The user blocked his/her note manually, eg. when he/she left the school for holidays. It can be reactivated at any time.'), ('forced', "The note is blocked by the the BDE and can't be manually reactivated.")], default='', max_length=255),
+ ),
+ migrations.AlterField(
+ model_name='transaction',
+ name='invalidity_reason',
+ field=models.CharField(blank=True, default='', max_length=255, verbose_name='invalidity reason'),
+ ),
+ ]
diff --git a/apps/note/models/notes.py b/apps/note/models/notes.py
index 877247df..9efdd1d0 100644
--- a/apps/note/models/notes.py
+++ b/apps/note/models/notes.py
@@ -70,8 +70,8 @@ class Note(PolymorphicModel):
"It can be reactivated at any time.")),
('forced', _("The note is blocked by the the BDE and can't be manually reactivated.")),
],
- null=True,
- default=None,
+ blank=True,
+ default="",
)
class Meta:
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index d10bf3a6..b89b405f 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -90,6 +90,9 @@ class TransactionTemplate(models.Model):
def get_absolute_url(self):
return reverse('note:template_update', args=(self.pk,))
+ def __str__(self):
+ return self.name
+
class Transaction(PolymorphicModel):
"""
@@ -150,8 +153,7 @@ class Transaction(PolymorphicModel):
invalidity_reason = models.CharField(
verbose_name=_('invalidity reason'),
max_length=255,
- default=None,
- null=True,
+ default='',
blank=True,
)
@@ -195,7 +197,7 @@ class Transaction(PolymorphicModel):
# When a transaction is declared valid, we ensure that the invalidity reason is null, if it was
# previously invalid
- self.invalidity_reason = None
+ self.invalidity_reason = ""
if source_balance > 9223372036854775807 or source_balance < -9223372036854775808\
or dest_balance > 9223372036854775807 or dest_balance < -9223372036854775808:
diff --git a/apps/scripts b/apps/scripts
index 4f5a7947..bac22dcb 160000
--- a/apps/scripts
+++ b/apps/scripts
@@ -1 +1 @@
-Subproject commit 4f5a794798a48cbbf10b42f0a519743fcbb96c33
+Subproject commit bac22dcbac9f3ddb981a5e63629a77ca2cb8f8ff
diff --git a/apps/treasury/models.py b/apps/treasury/models.py
index e57496ec..175829fe 100644
--- a/apps/treasury/models.py
+++ b/apps/treasury/models.py
@@ -109,6 +109,9 @@ class Invoice(models.Model):
verbose_name = _("invoice")
verbose_name_plural = _("invoices")
+ def __str__(self):
+ return _("Invoice #{id}").format(id=self.id)
+
class Product(models.Model):
"""
@@ -151,6 +154,9 @@ class Product(models.Model):
verbose_name = _("product")
verbose_name_plural = _("products")
+ def __str__(self):
+ return f"{self.designation} ({self.invoice})"
+
class RemittanceType(models.Model):
"""
@@ -256,6 +262,9 @@ class SpecialTransactionProxy(models.Model):
verbose_name = _("special transaction proxy")
verbose_name_plural = _("special transaction proxies")
+ def __str__(self):
+ return str(self.transaction)
+
class SogeCredit(models.Model):
"""
@@ -354,3 +363,6 @@ class SogeCredit(models.Model):
class Meta:
verbose_name = _("Credit from the Société générale")
verbose_name_plural = _("Credits from the Société générale")
+
+ def __str__(self):
+ return _("Soge credit for {user}").format(user=str(self.user))
From f3f746aba8c275b118ccea4837d820b15aac4b48 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 11:03:58 +0200
Subject: [PATCH 15/23] Plain text mode in reports
---
.../templates/note/mails/weekly_report.html | 13 +++-----
.../templates/note/mails/weekly_report.txt | 32 +++++++++++++++++++
apps/scripts | 2 +-
3 files changed, 38 insertions(+), 9 deletions(-)
create mode 100644 apps/note/templates/note/mails/weekly_report.txt
diff --git a/apps/note/templates/note/mails/weekly_report.html b/apps/note/templates/note/mails/weekly_report.html
index 871e09c2..6ed768a3 100644
--- a/apps/note/templates/note/mails/weekly_report.html
+++ b/apps/note/templates/note/mails/weekly_report.html
@@ -1,5 +1,7 @@
{% load pretty_money %}
+{% load getenv %}
{% load render_table from django_tables2 %}
+{% load static %}
{% load i18n %}
@@ -8,13 +10,8 @@
[Note Kfet] Rapport de la Note Kfet
-
-
+
+
@@ -27,7 +24,7 @@
Ensuite, un rapport vous est envoyé à la fréquence demandée seulement si vous avez consommé
depuis le dernier rapport.
Pour arrêter de recevoir des rapports, il vous suffit de modifier votre profil Note et de
- mettre la fréquence des rapports à 0 ou -1.
+ mettre la fréquence des rapports à 0.
Pour toutes suggestions par rapport à ce service, contactez
notekfet2020@lists.crans.org .
diff --git a/apps/note/templates/note/mails/weekly_report.txt b/apps/note/templates/note/mails/weekly_report.txt
new file mode 100644
index 00000000..3d9bcf67
--- /dev/null
+++ b/apps/note/templates/note/mails/weekly_report.txt
@@ -0,0 +1,32 @@
+{% load pretty_money %}
+{% load getenv %}
+{% load i18n %}
+
+Bonjour,
+
+Vous recevez ce mail car vous avez défini une « Fréquence des rapports » dans la Note.
+Le premier rapport récapitule toutes vos consommations depuis la création de votre compte.
+Ensuite, un rapport vous est envoyé à la fréquence demandée seulement si vous avez consommé
+depuis le dernier rapport.
+Pour arrêter de recevoir des rapports, il vous suffit de modifier votre profil Note et de
+mettre la fréquence des rapports à 0.
+Pour toutes suggestions par rapport à ce service, contactez notekfet2020@lists.crans.org.
+
+Rapport d'activité de {{ user.first_name|safe }} {{ user.last_name|safe }} (note : {{ user|safe }})
+depuis le {{ last_report }} jusqu'au {{ now }}.
+
+Dépenses totales : {{ outcoming|pretty_money }}
+Apports totaux : {{ incoming|pretty_money }}
+Différentiel : {{ diff|pretty_money }}
+Nouveau solde : {{ user.note.balance|pretty_money }}
+
+
+Rapport détaillé :
+
+| Source | Destination | Créée le | Quantité | Montant | Raison | Type | Total | Valide |
++----------------------+----------------------+---------------------+----------+----------+----------------------------------+------------------+----------+---------+
+{% for tr in last_transactions %}| {{ tr.source|safe|truncatechars:20|center:"20" }} | {{ tr.destination|safe|truncatechars:20|center:"20" }} | {{ tr.created_at|date:"Y-m-d H:i:s" }} | {{ tr.quantity|center:"8" }} | {{ tr.amount|pretty_money|center:"8" }} | {{ tr.reason|safe|truncatechars:32|center:"32" }} | {{ tr.type|safe|center:"16" }} | {{ tr.total|pretty_money|center:"8" }} | {{ tr.valid|yesno|center:"7" }} |
+{% endfor %}
+--
+Le BDE
+{% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %}
diff --git a/apps/scripts b/apps/scripts
index 4f5a7947..4506dd4d 160000
--- a/apps/scripts
+++ b/apps/scripts
@@ -1 +1 @@
-Subproject commit 4f5a794798a48cbbf10b42f0a519743fcbb96c33
+Subproject commit 4506dd4dc09a1255e68043b2c13afff7b3b72fce
From 0183ba193c30e53a58ec685d729d74cf876f5769 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 11:07:31 +0200
Subject: [PATCH 16/23] Plain text mode in reports
---
apps/scripts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/scripts b/apps/scripts
index bac22dcb..4506dd4d 160000
--- a/apps/scripts
+++ b/apps/scripts
@@ -1 +1 @@
-Subproject commit bac22dcbac9f3ddb981a5e63629a77ca2cb8f8ff
+Subproject commit 4506dd4dc09a1255e68043b2c13afff7b3b72fce
From 7a32c30b8c9a131f0a9de4adc6abb65eb613796e Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 11:23:05 +0200
Subject: [PATCH 17/23] Model names translations were missing
---
locale/de/LC_MESSAGES/django.po | 267 ++++++++++++++++++--------------
locale/fr/LC_MESSAGES/django.po | 265 +++++++++++++++++--------------
2 files changed, 292 insertions(+), 240 deletions(-)
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 674e5ce0..c3bed92d 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-06 20:16+0200\n"
+"POT-Creation-Date: 2020-09-07 11:14+0200\n"
"PO-Revision-Date: 2020-09-03 23:47+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -27,33 +27,33 @@ msgstr "Veranstaltung"
msgid "The end date must be after the start date."
msgstr "Das Abschlussdatum muss nach das Anfangsdatum sein."
-#: apps/activity/forms.py:76 apps/activity/models.py:262
+#: apps/activity/forms.py:76 apps/activity/models.py:268
msgid "You can't invite someone once the activity is started."
msgstr ""
"Sie dürfen nicht jemandem einladen wenn die Veranstaltung angefangen hat."
-#: apps/activity/forms.py:79 apps/activity/models.py:265
+#: apps/activity/forms.py:79 apps/activity/models.py:271
msgid "This activity is not validated yet."
msgstr "Diese Veranstaltung ist noch nicht bestätigt."
-#: apps/activity/forms.py:89 apps/activity/models.py:273
+#: apps/activity/forms.py:89 apps/activity/models.py:279
msgid "This person has been already invited 5 times this year."
msgstr "Diese Person wurde schon 5 mal dieses Jahr eingeladen."
-#: apps/activity/forms.py:93 apps/activity/models.py:277
+#: apps/activity/forms.py:93 apps/activity/models.py:283
msgid "This person is already invited."
msgstr "Diese Person wurde schon eingeladen."
-#: apps/activity/forms.py:97 apps/activity/models.py:281
+#: apps/activity/forms.py:97 apps/activity/models.py:287
msgid "You can't invite more than 3 people to this activity."
msgstr "Sie dürfen höchstens 3 Leute zu dieser Veranstaltung einladen."
#: apps/activity/models.py:28 apps/activity/models.py:63
-#: apps/member/models.py:200
+#: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:253 apps/note/models/transactions.py:26
-#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:302
+#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:296
#: apps/permission/models.py:329
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118
@@ -110,8 +110,8 @@ msgstr "Wo findet die Veranstaltung statt ? (z.B Kfet)"
msgid "type"
msgstr "Type"
-#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:305
-#: apps/note/models/notes.py:144 apps/treasury/models.py:267
+#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:304
+#: apps/note/models/notes.py:144 apps/treasury/models.py:276
#: apps/treasury/templates/treasury/sogecredit_detail.html:14
#: apps/wei/models.py:160 apps/wei/templates/wei/survey.html:15
msgid "user"
@@ -149,7 +149,7 @@ msgstr "Abschlussdatum"
#: apps/activity/models.py:118
#: apps/activity/templates/activity/includes/activity_info.html:50
-#: apps/note/models/transactions.py:146
+#: apps/note/models/transactions.py:149
msgid "valid"
msgstr "gültig"
@@ -181,42 +181,53 @@ msgstr "Eintritt"
msgid "entries"
msgstr "Eintritte"
-#: apps/activity/models.py:195
+#: apps/activity/models.py:192
+#, python-brace-format
+msgid "Entry for {guest}, invited by {note} to the activity {activity}"
+msgstr "Eintritt für {guest}, von {note} zur Vanstaltung {activity} eingeladen"
+
+#: apps/activity/models.py:194
+#, fuzzy, python-brace-format
+#| msgid "Entry for activity \"{}\""
+msgid "Entry for {note} to the activity {activity}"
+msgstr "Eintritt zur Veranstaltung \"{}\""
+
+#: apps/activity/models.py:201
msgid "Already entered on "
msgstr "Schon eingetretten "
-#: apps/activity/models.py:195 apps/activity/tables.py:54
+#: apps/activity/models.py:201 apps/activity/tables.py:54
msgid "{:%Y-%m-%d %H:%M:%S}"
msgstr "{:%Y-%m-%d %H:%M:%S}"
-#: apps/activity/models.py:203
+#: apps/activity/models.py:209
msgid "The balance is negative."
msgstr "Kontostand ist im Rot."
-#: apps/activity/models.py:233
+#: apps/activity/models.py:239
msgid "last name"
msgstr "Nachname"
-#: apps/activity/models.py:238
+#: apps/activity/models.py:244
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/templates/wei/weimembership_form.html:14
msgid "first name"
msgstr "Vorname"
-#: apps/activity/models.py:245
+#: apps/activity/models.py:251
msgid "inviter"
msgstr "Einlader"
-#: apps/activity/models.py:289
+#: apps/activity/models.py:295
msgid "guest"
msgstr "Gast"
-#: apps/activity/models.py:290
+#: apps/activity/models.py:296
msgid "guests"
msgstr "Gäste"
-#: apps/activity/models.py:302
+#: apps/activity/models.py:308
msgid "Invitation"
msgstr "Einladung"
@@ -240,7 +251,7 @@ msgstr "Eingetreten um "
msgid "remove"
msgstr "entfernen"
-#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:186
+#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:192
msgid "Type"
msgstr "Type"
@@ -270,7 +281,7 @@ msgid "Guests list"
msgstr "Gastliste"
#: apps/activity/templates/activity/activity_entry.html:14
-#: apps/note/models/transactions.py:259
+#: apps/note/models/transactions.py:253
#: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148
#: note_kfet/templates/base.html:70
@@ -278,13 +289,13 @@ msgid "Transfer"
msgstr "Überweisen"
#: apps/activity/templates/activity/activity_entry.html:18
-#: apps/note/models/transactions.py:318
+#: apps/note/models/transactions.py:312
#: apps/note/templates/note/transaction_form.html:21
msgid "Credit"
msgstr "Kredit"
#: apps/activity/templates/activity/activity_entry.html:21
-#: apps/note/models/transactions.py:318
+#: apps/note/models/transactions.py:312
#: apps/note/templates/note/transaction_form.html:25
msgid "Debit"
msgstr "Soll"
@@ -356,7 +367,7 @@ msgid "validate"
msgstr "validate"
#: apps/activity/templates/activity/includes/activity_info.html:71
-#: apps/logs/models.py:62 apps/note/tables.py:195
+#: apps/logs/models.py:64 apps/note/tables.py:195
msgid "edit"
msgstr "bearbeiten"
@@ -420,59 +431,64 @@ msgstr "Model"
msgid "identifier"
msgstr "Kennzeichnung"
-#: apps/logs/models.py:48
+#: apps/logs/models.py:49
msgid "previous data"
msgstr "ehemalige Daten"
-#: apps/logs/models.py:53
+#: apps/logs/models.py:55
msgid "new data"
msgstr "neue Daten"
-#: apps/logs/models.py:61
+#: apps/logs/models.py:63
msgid "create"
msgstr "schaffen"
-#: apps/logs/models.py:63 apps/note/tables.py:165 apps/note/tables.py:201
+#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
#: apps/permission/models.py:127 apps/treasury/tables.py:38
#: apps/wei/tables.py:75
msgid "delete"
msgstr "entfernen"
-#: apps/logs/models.py:66
+#: apps/logs/models.py:68
msgid "action"
msgstr "Aktion"
-#: apps/logs/models.py:74
+#: apps/logs/models.py:76
msgid "timestamp"
msgstr "Zeitstempel"
-#: apps/logs/models.py:78
+#: apps/logs/models.py:80
msgid "Logs cannot be destroyed."
msgstr "Logs können nicht entfernen sein."
-#: apps/logs/models.py:81
+#: apps/logs/models.py:83
msgid "changelog"
msgstr "Changelog"
-#: apps/logs/models.py:82
+#: apps/logs/models.py:84
msgid "changelogs"
msgstr "Changelogs"
-#: apps/member/admin.py:50 apps/member/models.py:227
+#: apps/logs/models.py:87
+#, python-brace-format
+msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
+msgstr "Changelog \"{action}\" für Model {model} an {timestamp}"
+
+#: apps/member/admin.py:50 apps/member/models.py:226
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "Mitgliedschaftpreis (bezahlte Studenten)"
-#: apps/member/admin.py:51 apps/member/models.py:232
+#: apps/member/admin.py:51 apps/member/models.py:231
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "Mitgliedschaftpreis (unbezahlte Studenten)"
-#: apps/member/admin.py:65 apps/member/models.py:316
+#: apps/member/admin.py:65 apps/member/models.py:315
msgid "roles"
msgstr "Rollen"
-#: apps/member/admin.py:66 apps/member/models.py:330
+#: apps/member/admin.py:66 apps/member/models.py:329
msgid "fee"
msgstr "Preis"
@@ -666,19 +682,19 @@ msgstr "bezahlt"
msgid "Tells if the user receive a salary."
msgstr "User ist bezahlt."
-#: apps/member/models.py:101 apps/treasury/tables.py:146
+#: apps/member/models.py:100 apps/treasury/tables.py:146
msgid "No"
msgstr "Nein"
-#: apps/member/models.py:102
+#: apps/member/models.py:101
msgid "Yes (receive them in french)"
msgstr "Ja (auf Fränzosich)"
-#: apps/member/models.py:103
+#: apps/member/models.py:102
msgid "Yes (receive them in english)"
msgstr "Ja (auf English)"
-#: apps/member/models.py:105
+#: apps/member/models.py:104
msgid ""
"Register on the mailing list to stay informed of the events of the campus (1 "
"mail/week)"
@@ -686,7 +702,7 @@ msgstr ""
"Melden Sie sich auf der Mailingliste an, um über die Ereignisse des Campus "
"informiert zu bleiben (1 Mail / Woche)"
-#: apps/member/models.py:110
+#: apps/member/models.py:109
msgid ""
"Register on the mailing list to stay informed of the sport events of the "
"campus (1 mail/week)"
@@ -694,7 +710,7 @@ msgstr ""
"Melden Sie sich auf der Mailingliste an, um über die Sportereignisse des "
"Campus informiert zu bleiben (1 Mail / Woche)"
-#: apps/member/models.py:115
+#: apps/member/models.py:114
msgid ""
"Register on the mailing list to stay informed of the art events of the "
"campus (1 mail/week)"
@@ -702,31 +718,31 @@ msgstr ""
"Melden Sie sich auf der Mailingliste an, um über die Kunstereignisse des "
"Campus informiert zu bleiben (1 Mail / Woche)"
-#: apps/member/models.py:119
+#: apps/member/models.py:118
msgid "report frequency (in days)"
msgstr "Bericht Frequenz (Tagen)"
-#: apps/member/models.py:124
+#: apps/member/models.py:123
msgid "last report date"
msgstr "letzen Bericht Datum"
-#: apps/member/models.py:129
+#: apps/member/models.py:128
msgid "email confirmed"
msgstr "email bestätigt"
-#: apps/member/models.py:134
+#: apps/member/models.py:133
msgid "registration valid"
msgstr "Anmeldung gültig"
-#: apps/member/models.py:163 apps/member/models.py:164
+#: apps/member/models.py:162 apps/member/models.py:163
msgid "user profile"
msgstr "Userprofile"
-#: apps/member/models.py:174
+#: apps/member/models.py:173
msgid "Activate your Note Kfet account"
msgstr "Ihre Note Kfet Konto bestätigen"
-#: apps/member/models.py:205
+#: apps/member/models.py:204
#: apps/member/templates/member/includes/club_info.html:55
#: apps/member/templates/member/includes/profile_info.html:31
#: apps/registration/templates/registration/future_profile_detail.html:22
@@ -735,88 +751,88 @@ msgstr "Ihre Note Kfet Konto bestätigen"
msgid "email"
msgstr "Email"
-#: apps/member/models.py:212
+#: apps/member/models.py:211
msgid "parent club"
msgstr "Urclub"
-#: apps/member/models.py:221
+#: apps/member/models.py:220
msgid "require memberships"
msgstr "erfordern Mitgliedschaft"
-#: apps/member/models.py:222
+#: apps/member/models.py:221
msgid "Uncheck if this club don't require memberships."
msgstr ""
"Deaktivieren Sie diese Option, wenn für diesen Club keine Mitgliedschaft "
"erforderlich ist."
-#: apps/member/models.py:238
+#: apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:26
msgid "membership duration"
msgstr "Mitgliedscahftzeit"
-#: apps/member/models.py:239
+#: apps/member/models.py:238
msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "Wie lang am höchsten eine Mitgliedschaft dauern kann."
-#: apps/member/models.py:246
+#: apps/member/models.py:245
#: apps/member/templates/member/includes/club_info.html:16
msgid "membership start"
msgstr "Mitgliedschaftanfangsdatum"
-#: apps/member/models.py:247
+#: apps/member/models.py:246
msgid "Date from which the members can renew their membership."
msgstr "Ab wann kann man sein Mitgliedschaft erneuern."
-#: apps/member/models.py:253
+#: apps/member/models.py:252
#: apps/member/templates/member/includes/club_info.html:21
msgid "membership end"
msgstr "Mitgliedschaftenddatum"
-#: apps/member/models.py:254
+#: apps/member/models.py:253
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Maximales Datum einer Mitgliedschaft, nach dem Mitglieder es erneuern müssen."
-#: apps/member/models.py:286 apps/member/models.py:311
+#: apps/member/models.py:285 apps/member/models.py:310
#: apps/note/models/notes.py:185
msgid "club"
msgstr "Club"
-#: apps/member/models.py:287
+#: apps/member/models.py:286
msgid "clubs"
msgstr "Clubs"
-#: apps/member/models.py:321
+#: apps/member/models.py:320
msgid "membership starts on"
msgstr "Mitgliedschaft fängt an"
-#: apps/member/models.py:325
+#: apps/member/models.py:324
msgid "membership ends on"
msgstr "Mitgliedschaft endet am"
-#: apps/member/models.py:420
+#: apps/member/models.py:419
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Die Rolle {role} ist nicht erlaubt für das Club {club}."
-#: apps/member/models.py:429 apps/member/views.py:628
+#: apps/member/models.py:428 apps/member/views.py:628
msgid "User is already a member of the club"
msgstr "User ist schon ein Mitglied dieser club"
-#: apps/member/models.py:441
+#: apps/member/models.py:440
msgid "User is not a member of the parent club"
msgstr "User ist noch nicht Mitglied des Urclubs"
-#: apps/member/models.py:489
+#: apps/member/models.py:488
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Mitgliedschaft von {user} für das Club {club}"
-#: apps/member/models.py:492 apps/note/models/transactions.py:359
+#: apps/member/models.py:491 apps/note/models/transactions.py:353
msgid "membership"
msgstr "Mitgliedschaft"
-#: apps/member/models.py:493
+#: apps/member/models.py:492
msgid "memberships"
msgstr "Mitgliedschaften"
@@ -1116,22 +1132,22 @@ msgstr "Rollen in diesen Club bearbeiten"
msgid "Members of the club"
msgstr "Mitlglieder dieses Club"
-#: apps/note/admin.py:129 apps/note/models/transactions.py:106
+#: apps/note/admin.py:129 apps/note/models/transactions.py:109
msgid "source"
msgstr "Sender"
#: apps/note/admin.py:137 apps/note/admin.py:205
-#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:119
+#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:122
msgid "destination"
msgstr "Empfänger"
#: apps/note/admin.py:210 apps/note/models/transactions.py:60
-#: apps/note/models/transactions.py:137
+#: apps/note/models/transactions.py:140
msgid "amount"
msgstr "Anzahl"
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
-#: apps/note/models/transactions.py:224
+#: apps/note/models/transactions.py:226
msgid ""
"The transaction can't be saved since the source note or the destination note "
"is not active."
@@ -1191,7 +1207,7 @@ msgstr "letztes mal im Rot"
msgid "display image"
msgstr "Bild"
-#: apps/note/models/notes.py:54 apps/note/models/transactions.py:129
+#: apps/note/models/notes.py:54 apps/note/models/transactions.py:132
msgid "created at"
msgstr "erschafft am"
@@ -1316,33 +1332,33 @@ msgstr "Transaktionsvorlage"
msgid "transaction templates"
msgstr "Transaktionsvorlagen"
-#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
+#: apps/note/models/transactions.py:115 apps/note/models/transactions.py:128
#: apps/note/tables.py:34 apps/note/tables.py:44
msgid "used alias"
msgstr "benutzte Aliasen"
-#: apps/note/models/transactions.py:133
+#: apps/note/models/transactions.py:136
msgid "quantity"
msgstr "Anzahl"
-#: apps/note/models/transactions.py:141
+#: apps/note/models/transactions.py:144
msgid "reason"
msgstr "Grund"
-#: apps/note/models/transactions.py:151 apps/note/tables.py:140
+#: apps/note/models/transactions.py:154 apps/note/tables.py:140
msgid "invalidity reason"
msgstr "Ungültigkeit Grund"
-#: apps/note/models/transactions.py:159
+#: apps/note/models/transactions.py:161
msgid "transaction"
msgstr "Transaktion"
-#: apps/note/models/transactions.py:160
+#: apps/note/models/transactions.py:162
#: apps/treasury/templates/treasury/sogecredit_detail.html:22
msgid "transactions"
msgstr "Transaktionen"
-#: apps/note/models/transactions.py:182
+#: apps/note/models/transactions.py:184
#, python-brace-format
msgid ""
"You can't update the {field} on a Transaction. Please invalidate it and "
@@ -1351,7 +1367,7 @@ msgstr ""
"Sie können das {field} einer Transaktion nicht aktualisieren. Bitte machen "
"Sie es ungültig und erstellen Sie eine andere."
-#: apps/note/models/transactions.py:202
+#: apps/note/models/transactions.py:204
msgid ""
"The note balances must be between - 92 233 720 368 547 758.08 € and 92 233 "
"720 368 547 758.07 €."
@@ -1359,34 +1375,34 @@ msgstr ""
"Die Notenguthaben müssen zwischen - 92 233 720 368 547 758,08 € und 92 233 "
"720 368 547 758,07 € liegen."
-#: apps/note/models/transactions.py:279
+#: apps/note/models/transactions.py:273
msgid ""
"The destination of this transaction must equal to the destination of the "
"template."
msgstr ""
"Der Empfänger dieser Transaktion muss dem Empfänger der Vorlage entsprechen."
-#: apps/note/models/transactions.py:288
+#: apps/note/models/transactions.py:282
msgid "Template"
msgstr "Vorlage"
-#: apps/note/models/transactions.py:291
+#: apps/note/models/transactions.py:285
msgid "recurrent transaction"
msgstr "wiederkehrende Transaktion"
-#: apps/note/models/transactions.py:292
+#: apps/note/models/transactions.py:286
msgid "recurrent transactions"
msgstr "wiederkehrende Transaktionen"
-#: apps/note/models/transactions.py:307
+#: apps/note/models/transactions.py:301
msgid "first_name"
msgstr "Vorname"
-#: apps/note/models/transactions.py:312
+#: apps/note/models/transactions.py:306
msgid "bank"
msgstr "Bank"
-#: apps/note/models/transactions.py:329
+#: apps/note/models/transactions.py:323
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
@@ -1394,19 +1410,19 @@ msgstr ""
"Eine Sondertransaktion ist nur zwischen einer Note, die einer "
"Zahlungsmethode zugeordnet ist, und einem User oder einem Club möglich"
-#: apps/note/models/transactions.py:337
+#: apps/note/models/transactions.py:331
msgid "Special transaction"
msgstr "Sondertransaktion"
-#: apps/note/models/transactions.py:338
+#: apps/note/models/transactions.py:332
msgid "Special transactions"
msgstr "Sondertranskationen"
-#: apps/note/models/transactions.py:354
+#: apps/note/models/transactions.py:348
msgid "membership transaction"
msgstr "Mitgliedschafttransaktion"
-#: apps/note/models/transactions.py:355 apps/treasury/models.py:273
+#: apps/note/models/transactions.py:349 apps/treasury/models.py:282
msgid "membership transactions"
msgstr "Mitgliedschaftttransaktionen"
@@ -1678,7 +1694,7 @@ msgstr ""
"Sie haben nicht die Berechtigung, das Feld {field} in dieser Instanz von "
"Modell {app_label} zu ändern. {model_name}"
-#: apps/permission/signals.py:73 apps/permission/views.py:89
+#: apps/permission/signals.py:73 apps/permission/views.py:101
#, python-brace-format
msgid ""
"You don't have the permission to add an instance of model {app_label}."
@@ -1736,7 +1752,7 @@ msgstr "Abfrage:"
msgid "No associated permission"
msgstr "Keine zugehörige Berechtigung"
-#: apps/permission/views.py:56
+#: apps/permission/views.py:68
#, python-brace-format
msgid ""
"You don't have the permission to update this instance of the model "
@@ -1746,7 +1762,7 @@ msgstr ""
"diesen Parametern zu aktualisieren. Bitte korrigieren Sie Ihre Daten und "
"versuchen Sie es erneut."
-#: apps/permission/views.py:60
+#: apps/permission/views.py:72
#, python-brace-format
msgid ""
"You don't have the permission to create an instance of the model \"{model}\" "
@@ -1756,11 +1772,11 @@ msgstr ""
"diesen Parametern zu erstellen. Bitte korrigieren Sie Ihre Daten und "
"versuchen Sie es erneut."
-#: apps/permission/views.py:96 note_kfet/templates/base.html:106
+#: apps/permission/views.py:108 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Rechten"
-#: apps/permission/views.py:101
+#: apps/permission/views.py:113
msgid "All rights"
msgstr "Alle Rechten"
@@ -1967,7 +1983,7 @@ msgstr "Überweisung ist bereits geschlossen."
msgid "You can't change the type of the remittance."
msgstr "Sie können die Art der Überweisung nicht ändern."
-#: apps/treasury/forms.py:123 apps/treasury/models.py:252
+#: apps/treasury/forms.py:123 apps/treasury/models.py:258
#: apps/treasury/tables.py:97 apps/treasury/tables.py:105
#: apps/treasury/templates/treasury/invoice_list.html:16
#: apps/treasury/templates/treasury/remittance_list.html:16
@@ -1999,7 +2015,7 @@ msgstr "Beschreibung"
msgid "Address"
msgstr "Adresse"
-#: apps/treasury/models.py:60 apps/treasury/models.py:180
+#: apps/treasury/models.py:60 apps/treasury/models.py:186
msgid "Date"
msgstr "Datum"
@@ -2019,7 +2035,7 @@ msgstr "Eine Rechnung kann nicht bearbeitet werden, wenn sie gesperrt ist."
msgid "tex source"
msgstr "Tex Quelle"
-#: apps/treasury/models.py:109 apps/treasury/models.py:122
+#: apps/treasury/models.py:109 apps/treasury/models.py:125
msgid "invoice"
msgstr "Rechnung"
@@ -2027,67 +2043,73 @@ msgstr "Rechnung"
msgid "invoices"
msgstr "Rechnungen"
-#: apps/treasury/models.py:127
+#: apps/treasury/models.py:113
+#, fuzzy, python-brace-format
+#| msgid "Invoice #{:d}"
+msgid "Invoice #{id}"
+msgstr "Rechnung #{:d}"
+
+#: apps/treasury/models.py:130
msgid "Designation"
msgstr "Bezeichnung"
-#: apps/treasury/models.py:131
+#: apps/treasury/models.py:134
msgid "Quantity"
msgstr "Qualität"
-#: apps/treasury/models.py:135
+#: apps/treasury/models.py:138
msgid "Unit price"
msgstr "Einzelpreis"
-#: apps/treasury/models.py:151
+#: apps/treasury/models.py:154
msgid "product"
msgstr "Produkt"
-#: apps/treasury/models.py:152
+#: apps/treasury/models.py:155
msgid "products"
msgstr "Produkten"
-#: apps/treasury/models.py:169
+#: apps/treasury/models.py:175
msgid "remittance type"
msgstr "Überweisungstyp"
-#: apps/treasury/models.py:170
+#: apps/treasury/models.py:176
msgid "remittance types"
msgstr "Überweisungstypen"
-#: apps/treasury/models.py:191
+#: apps/treasury/models.py:197
msgid "Comment"
msgstr "Kommentar"
-#: apps/treasury/models.py:196
+#: apps/treasury/models.py:202
msgid "Closed"
msgstr "Geschlossen"
-#: apps/treasury/models.py:200
+#: apps/treasury/models.py:206
msgid "remittance"
msgstr "Überweisung"
-#: apps/treasury/models.py:201
+#: apps/treasury/models.py:207
msgid "remittances"
msgstr "Überweisungen"
-#: apps/treasury/models.py:233
+#: apps/treasury/models.py:239
msgid "Remittance #{:d}: {}"
msgstr "Überweisung #{:d}:{}"
-#: apps/treasury/models.py:256
+#: apps/treasury/models.py:262
msgid "special transaction proxy"
msgstr "spezielle Transaktion Proxy"
-#: apps/treasury/models.py:257
+#: apps/treasury/models.py:263
msgid "special transaction proxies"
msgstr "spezielle Transaktion Proxies"
-#: apps/treasury/models.py:279
+#: apps/treasury/models.py:288
msgid "credit transaction"
msgstr "Kredit Transaktion"
-#: apps/treasury/models.py:343
+#: apps/treasury/models.py:352
msgid ""
"This user doesn't have enough money to pay the memberships with its note. "
"Please ask her/him to credit the note before invalidating this credit."
@@ -2095,15 +2117,20 @@ msgstr ""
"Dieser Benutzer hat nicht genug Geld, um die Mitgliedschaften mit seiner "
"Note zu bezahlen."
-#: apps/treasury/models.py:355
+#: apps/treasury/models.py:364
#: apps/treasury/templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale"
msgstr "Kredit von der Société générale"
-#: apps/treasury/models.py:356
+#: apps/treasury/models.py:365
msgid "Credits from the Société générale"
msgstr "Krediten von der Société générale"
+#: apps/treasury/models.py:368
+#, python-brace-format
+msgid "Soge credit for {user}"
+msgstr "Kredit von der Société générale für {user}"
+
#: apps/treasury/tables.py:20
msgid "Invoice #{:d}"
msgstr "Rechnung #{:d}"
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 353e342a..7c2ee43b 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-06 20:16+0200\n"
+"POT-Creation-Date: 2020-09-07 11:14+0200\n"
"PO-Revision-Date: 2020-09-02 23:18+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -27,33 +27,33 @@ msgstr "activité"
msgid "The end date must be after the start date."
msgstr "La date de fin doit être après celle de début."
-#: apps/activity/forms.py:76 apps/activity/models.py:262
+#: apps/activity/forms.py:76 apps/activity/models.py:268
msgid "You can't invite someone once the activity is started."
msgstr ""
"Vous ne pouvez pas inviter quelqu'un une fois que l'activité a démarré."
-#: apps/activity/forms.py:79 apps/activity/models.py:265
+#: apps/activity/forms.py:79 apps/activity/models.py:271
msgid "This activity is not validated yet."
msgstr "Cette activité n'est pas encore validée."
-#: apps/activity/forms.py:89 apps/activity/models.py:273
+#: apps/activity/forms.py:89 apps/activity/models.py:279
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:93 apps/activity/models.py:277
+#: apps/activity/forms.py:93 apps/activity/models.py:283
msgid "This person is already invited."
msgstr "Cette personne est déjà invitée."
-#: apps/activity/forms.py:97 apps/activity/models.py:281
+#: apps/activity/forms.py:97 apps/activity/models.py:287
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:28 apps/activity/models.py:63
-#: apps/member/models.py:200
+#: apps/member/models.py:199
#: apps/member/templates/member/includes/club_info.html:4
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/note/models/notes.py:253 apps/note/models/transactions.py:26
-#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:302
+#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:296
#: apps/permission/models.py:329
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/models.py:66 apps/wei/models.py:118
@@ -110,8 +110,8 @@ msgstr "Lieu où l'activité est organisée, par exemple la Kfet."
msgid "type"
msgstr "type"
-#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:305
-#: apps/note/models/notes.py:144 apps/treasury/models.py:267
+#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:304
+#: apps/note/models/notes.py:144 apps/treasury/models.py:276
#: apps/treasury/templates/treasury/sogecredit_detail.html:14
#: apps/wei/models.py:160 apps/wei/templates/wei/survey.html:15
msgid "user"
@@ -149,7 +149,7 @@ msgstr "date de fin"
#: apps/activity/models.py:118
#: apps/activity/templates/activity/includes/activity_info.html:50
-#: apps/note/models/transactions.py:146
+#: apps/note/models/transactions.py:149
msgid "valid"
msgstr "valide"
@@ -181,42 +181,52 @@ msgstr "entrée"
msgid "entries"
msgstr "entrées"
-#: apps/activity/models.py:195
+#: apps/activity/models.py:192
+#, python-brace-format
+msgid "Entry for {guest}, invited by {note} to the activity {activity}"
+msgstr "Entrée pour {guest}, invité par {note} à l'activité {activity}"
+
+#: apps/activity/models.py:194
+#, python-brace-format
+msgid "Entry for {note} to the activity {activity}"
+msgstr "Entrée de la note {note} pour l'activité « {activity} »"
+
+#: apps/activity/models.py:201
msgid "Already entered on "
msgstr "Déjà rentré le "
-#: apps/activity/models.py:195 apps/activity/tables.py:54
+#: apps/activity/models.py:201 apps/activity/tables.py:54
msgid "{:%Y-%m-%d %H:%M:%S}"
msgstr "{:%d/%m/%Y %H:%M:%S}"
-#: apps/activity/models.py:203
+#: apps/activity/models.py:209
msgid "The balance is negative."
msgstr "La note est en négatif."
-#: apps/activity/models.py:233
+#: apps/activity/models.py:239
msgid "last name"
msgstr "nom de famille"
-#: apps/activity/models.py:238
+#: apps/activity/models.py:244
#: apps/member/templates/member/includes/profile_info.html:4
#: apps/registration/templates/registration/future_profile_detail.html:16
#: apps/wei/templates/wei/weimembership_form.html:14
msgid "first name"
msgstr "prénom"
-#: apps/activity/models.py:245
+#: apps/activity/models.py:251
msgid "inviter"
msgstr "hôte"
-#: apps/activity/models.py:289
+#: apps/activity/models.py:295
msgid "guest"
msgstr "invité"
-#: apps/activity/models.py:290
+#: apps/activity/models.py:296
msgid "guests"
msgstr "invités"
-#: apps/activity/models.py:302
+#: apps/activity/models.py:308
msgid "Invitation"
msgstr "Invitation"
@@ -240,7 +250,7 @@ msgstr "Entré le "
msgid "remove"
msgstr "supprimer"
-#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:186
+#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:192
msgid "Type"
msgstr "Type"
@@ -270,7 +280,7 @@ msgid "Guests list"
msgstr "Liste des invités"
#: apps/activity/templates/activity/activity_entry.html:14
-#: apps/note/models/transactions.py:259
+#: apps/note/models/transactions.py:253
#: apps/note/templates/note/transaction_form.html:16
#: apps/note/templates/note/transaction_form.html:148
#: note_kfet/templates/base.html:70
@@ -278,13 +288,13 @@ msgid "Transfer"
msgstr "Virement"
#: apps/activity/templates/activity/activity_entry.html:18
-#: apps/note/models/transactions.py:318
+#: apps/note/models/transactions.py:312
#: apps/note/templates/note/transaction_form.html:21
msgid "Credit"
msgstr "Crédit"
#: apps/activity/templates/activity/activity_entry.html:21
-#: apps/note/models/transactions.py:318
+#: apps/note/models/transactions.py:312
#: apps/note/templates/note/transaction_form.html:25
msgid "Debit"
msgstr "Débit"
@@ -356,7 +366,7 @@ msgid "validate"
msgstr "valider"
#: apps/activity/templates/activity/includes/activity_info.html:71
-#: apps/logs/models.py:62 apps/note/tables.py:195
+#: apps/logs/models.py:64 apps/note/tables.py:195
msgid "edit"
msgstr "modifier"
@@ -422,59 +432,64 @@ msgstr "modèle"
msgid "identifier"
msgstr "identifiant"
-#: apps/logs/models.py:48
+#: apps/logs/models.py:49
msgid "previous data"
msgstr "données précédentes"
-#: apps/logs/models.py:53
+#: apps/logs/models.py:55
msgid "new data"
msgstr "ouvelles données"
-#: apps/logs/models.py:61
+#: apps/logs/models.py:63
msgid "create"
msgstr "créer"
-#: apps/logs/models.py:63 apps/note/tables.py:165 apps/note/tables.py:201
+#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:201
#: apps/permission/models.py:127 apps/treasury/tables.py:38
#: apps/wei/tables.py:75
msgid "delete"
msgstr "supprimer"
-#: apps/logs/models.py:66
+#: apps/logs/models.py:68
msgid "action"
msgstr "action"
-#: apps/logs/models.py:74
+#: apps/logs/models.py:76
msgid "timestamp"
msgstr "date"
-#: apps/logs/models.py:78
+#: apps/logs/models.py:80
msgid "Logs cannot be destroyed."
msgstr "Les logs ne peuvent pas être détruits."
-#: apps/logs/models.py:81
+#: apps/logs/models.py:83
msgid "changelog"
msgstr "journal de modification"
-#: apps/logs/models.py:82
+#: apps/logs/models.py:84
msgid "changelogs"
msgstr "journaux de modifications"
-#: apps/member/admin.py:50 apps/member/models.py:227
+#: apps/logs/models.py:87
+#, python-brace-format
+msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
+msgstr "Changelog de type « {action} » pour le modèle {model} à {timestamp}"
+
+#: apps/member/admin.py:50 apps/member/models.py:226
#: apps/member/templates/member/includes/club_info.html:34
msgid "membership fee (paid students)"
msgstr "cotisation pour adhérer (normalien élève)"
-#: apps/member/admin.py:51 apps/member/models.py:232
+#: apps/member/admin.py:51 apps/member/models.py:231
#: apps/member/templates/member/includes/club_info.html:37
msgid "membership fee (unpaid students)"
msgstr "cotisation pour adhérer (normalien étudiant)"
-#: apps/member/admin.py:65 apps/member/models.py:316
+#: apps/member/admin.py:65 apps/member/models.py:315
msgid "roles"
msgstr "rôles"
-#: apps/member/admin.py:66 apps/member/models.py:330
+#: apps/member/admin.py:66 apps/member/models.py:329
msgid "fee"
msgstr "cotisation"
@@ -668,19 +683,19 @@ msgstr "payé"
msgid "Tells if the user receive a salary."
msgstr "Indique si l'utilisateur perçoit un salaire."
-#: apps/member/models.py:101 apps/treasury/tables.py:146
+#: apps/member/models.py:100 apps/treasury/tables.py:146
msgid "No"
msgstr "Non"
-#: apps/member/models.py:102
+#: apps/member/models.py:101
msgid "Yes (receive them in french)"
msgstr "Oui (les recevoir en français)"
-#: apps/member/models.py:103
+#: apps/member/models.py:102
msgid "Yes (receive them in english)"
msgstr "Oui (les recevoir en anglais)"
-#: apps/member/models.py:105
+#: apps/member/models.py:104
msgid ""
"Register on the mailing list to stay informed of the events of the campus (1 "
"mail/week)"
@@ -688,7 +703,7 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des événements sur "
"le campus (1 mail par semaine)"
-#: apps/member/models.py:110
+#: apps/member/models.py:109
msgid ""
"Register on the mailing list to stay informed of the sport events of the "
"campus (1 mail/week)"
@@ -696,7 +711,7 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités "
"sportives sur le campus (1 mail par semaine)"
-#: apps/member/models.py:115
+#: apps/member/models.py:114
msgid ""
"Register on the mailing list to stay informed of the art events of the "
"campus (1 mail/week)"
@@ -704,31 +719,31 @@ msgstr ""
"S'inscrire sur la liste de diffusion pour rester informé des actualités "
"artistiques sur le campus (1 mail par semaine)"
-#: apps/member/models.py:119
+#: apps/member/models.py:118
msgid "report frequency (in days)"
msgstr "fréquence des rapports (en jours)"
-#: apps/member/models.py:124
+#: apps/member/models.py:123
msgid "last report date"
msgstr "date de dernier rapport"
-#: apps/member/models.py:129
+#: apps/member/models.py:128
msgid "email confirmed"
msgstr "adresse email confirmée"
-#: apps/member/models.py:134
+#: apps/member/models.py:133
msgid "registration valid"
msgstr "inscription valide"
-#: apps/member/models.py:163 apps/member/models.py:164
+#: apps/member/models.py:162 apps/member/models.py:163
msgid "user profile"
msgstr "profil utilisateur"
-#: apps/member/models.py:174
+#: apps/member/models.py:173
msgid "Activate your Note Kfet account"
msgstr "Activez votre compte Note Kfet"
-#: apps/member/models.py:205
+#: apps/member/models.py:204
#: apps/member/templates/member/includes/club_info.html:55
#: apps/member/templates/member/includes/profile_info.html:31
#: apps/registration/templates/registration/future_profile_detail.html:22
@@ -737,88 +752,88 @@ msgstr "Activez votre compte Note Kfet"
msgid "email"
msgstr "courriel"
-#: apps/member/models.py:212
+#: apps/member/models.py:211
msgid "parent club"
msgstr "club parent"
-#: apps/member/models.py:221
+#: apps/member/models.py:220
msgid "require memberships"
msgstr "nécessite des adhésions"
-#: apps/member/models.py:222
+#: apps/member/models.py:221
msgid "Uncheck if this club don't require memberships."
msgstr "Décochez si ce club n'utilise pas d'adhésions."
-#: apps/member/models.py:238
+#: apps/member/models.py:237
#: apps/member/templates/member/includes/club_info.html:26
msgid "membership duration"
msgstr "durée de l'adhésion"
-#: apps/member/models.py:239
+#: apps/member/models.py:238
msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)."
-#: apps/member/models.py:246
+#: apps/member/models.py:245
#: apps/member/templates/member/includes/club_info.html:16
msgid "membership start"
msgstr "début de l'adhésion"
-#: apps/member/models.py:247
+#: apps/member/models.py:246
msgid "Date from which the members can renew their membership."
msgstr ""
"Date à partir de laquelle les adhérents peuvent renouveler leur adhésion."
-#: apps/member/models.py:253
+#: apps/member/models.py:252
#: apps/member/templates/member/includes/club_info.html:21
msgid "membership end"
msgstr "fin de l'adhésion"
-#: apps/member/models.py:254
+#: apps/member/models.py:253
msgid "Maximal date of a membership, after which members must renew it."
msgstr ""
"Date maximale d'une fin d'adhésion, après laquelle les adhérents doivent la "
"renouveler."
-#: apps/member/models.py:286 apps/member/models.py:311
+#: apps/member/models.py:285 apps/member/models.py:310
#: apps/note/models/notes.py:185
msgid "club"
msgstr "club"
-#: apps/member/models.py:287
+#: apps/member/models.py:286
msgid "clubs"
msgstr "clubs"
-#: apps/member/models.py:321
+#: apps/member/models.py:320
msgid "membership starts on"
msgstr "l'adhésion commence le"
-#: apps/member/models.py:325
+#: apps/member/models.py:324
msgid "membership ends on"
msgstr "l'adhésion finit le"
-#: apps/member/models.py:420
+#: apps/member/models.py:419
#, python-brace-format
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
-#: apps/member/models.py:429 apps/member/views.py:628
+#: apps/member/models.py:428 apps/member/views.py:628
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
-#: apps/member/models.py:441
+#: apps/member/models.py:440
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
-#: apps/member/models.py:489
+#: apps/member/models.py:488
#, python-brace-format
msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}"
-#: apps/member/models.py:492 apps/note/models/transactions.py:359
+#: apps/member/models.py:491 apps/note/models/transactions.py:353
msgid "membership"
msgstr "adhésion"
-#: apps/member/models.py:493
+#: apps/member/models.py:492
msgid "memberships"
msgstr "adhésions"
@@ -1118,22 +1133,22 @@ msgstr "Gérer les rôles d'un utilisateur dans le club"
msgid "Members of the club"
msgstr "Membres du club"
-#: apps/note/admin.py:129 apps/note/models/transactions.py:106
+#: apps/note/admin.py:129 apps/note/models/transactions.py:109
msgid "source"
msgstr "source"
#: apps/note/admin.py:137 apps/note/admin.py:205
-#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:119
+#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:122
msgid "destination"
msgstr "destination"
#: apps/note/admin.py:210 apps/note/models/transactions.py:60
-#: apps/note/models/transactions.py:137
+#: apps/note/models/transactions.py:140
msgid "amount"
msgstr "montant"
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
-#: apps/note/models/transactions.py:224
+#: apps/note/models/transactions.py:226
msgid ""
"The transaction can't be saved since the source note or the destination note "
"is not active."
@@ -1193,7 +1208,7 @@ msgstr "dernier instant où la note était en négatif"
msgid "display image"
msgstr "image affichée"
-#: apps/note/models/notes.py:54 apps/note/models/transactions.py:129
+#: apps/note/models/notes.py:54 apps/note/models/transactions.py:132
msgid "created at"
msgstr "créée le"
@@ -1319,33 +1334,33 @@ msgstr "modèle de transaction"
msgid "transaction templates"
msgstr "modèles de transaction"
-#: apps/note/models/transactions.py:112 apps/note/models/transactions.py:125
+#: apps/note/models/transactions.py:115 apps/note/models/transactions.py:128
#: apps/note/tables.py:34 apps/note/tables.py:44
msgid "used alias"
msgstr "alias utilisé"
-#: apps/note/models/transactions.py:133
+#: apps/note/models/transactions.py:136
msgid "quantity"
msgstr "quantité"
-#: apps/note/models/transactions.py:141
+#: apps/note/models/transactions.py:144
msgid "reason"
msgstr "raison"
-#: apps/note/models/transactions.py:151 apps/note/tables.py:140
+#: apps/note/models/transactions.py:154 apps/note/tables.py:140
msgid "invalidity reason"
msgstr "motif d'invalidité"
-#: apps/note/models/transactions.py:159
+#: apps/note/models/transactions.py:161
msgid "transaction"
msgstr "transaction"
-#: apps/note/models/transactions.py:160
+#: apps/note/models/transactions.py:162
#: apps/treasury/templates/treasury/sogecredit_detail.html:22
msgid "transactions"
msgstr "transactions"
-#: apps/note/models/transactions.py:182
+#: apps/note/models/transactions.py:184
#, python-brace-format
msgid ""
"You can't update the {field} on a Transaction. Please invalidate it and "
@@ -1354,7 +1369,7 @@ msgstr ""
"Vous ne pouvez pas mettre à jour le champ {field} dans une transaction. "
"Merci de l'invalider et d'en créer une autre."
-#: apps/note/models/transactions.py:202
+#: apps/note/models/transactions.py:204
msgid ""
"The note balances must be between - 92 233 720 368 547 758.08 € and 92 233 "
"720 368 547 758.07 €."
@@ -1363,7 +1378,7 @@ msgstr ""
"€ et 92 233 720 368 547 758.07 €. Ne cherchez pas à capitaliser l'argent du "
"BDE."
-#: apps/note/models/transactions.py:279
+#: apps/note/models/transactions.py:273
msgid ""
"The destination of this transaction must equal to the destination of the "
"template."
@@ -1371,27 +1386,27 @@ msgstr ""
"Le destinataire de cette transaction doit être identique à celui du bouton "
"utilisé."
-#: apps/note/models/transactions.py:288
+#: apps/note/models/transactions.py:282
msgid "Template"
msgstr "Bouton"
-#: apps/note/models/transactions.py:291
+#: apps/note/models/transactions.py:285
msgid "recurrent transaction"
msgstr "transaction issue de bouton"
-#: apps/note/models/transactions.py:292
+#: apps/note/models/transactions.py:286
msgid "recurrent transactions"
msgstr "transactions issues de boutons"
-#: apps/note/models/transactions.py:307
+#: apps/note/models/transactions.py:301
msgid "first_name"
msgstr "prénom"
-#: apps/note/models/transactions.py:312
+#: apps/note/models/transactions.py:306
msgid "bank"
msgstr "banque"
-#: apps/note/models/transactions.py:329
+#: apps/note/models/transactions.py:323
msgid ""
"A special transaction is only possible between a Note associated to a "
"payment method and a User or a Club"
@@ -1399,19 +1414,19 @@ msgstr ""
"Une transaction spéciale n'est possible que entre une note associée à un "
"mode de paiement et un utilisateur ou un club"
-#: apps/note/models/transactions.py:337
+#: apps/note/models/transactions.py:331
msgid "Special transaction"
msgstr "Transaction de crédit/retrait"
-#: apps/note/models/transactions.py:338
+#: apps/note/models/transactions.py:332
msgid "Special transactions"
msgstr "Transactions de crédit/retrait"
-#: apps/note/models/transactions.py:354
+#: apps/note/models/transactions.py:348
msgid "membership transaction"
msgstr "transaction d'adhésion"
-#: apps/note/models/transactions.py:355 apps/treasury/models.py:273
+#: apps/note/models/transactions.py:349 apps/treasury/models.py:282
msgid "membership transactions"
msgstr "transactions d'adhésion"
@@ -1685,7 +1700,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}."
-#: apps/permission/signals.py:73 apps/permission/views.py:89
+#: apps/permission/signals.py:73 apps/permission/views.py:101
#, python-brace-format
msgid ""
"You don't have the permission to add an instance of model {app_label}."
@@ -1744,7 +1759,7 @@ msgstr "Requête :"
msgid "No associated permission"
msgstr "Pas de permission associée"
-#: apps/permission/views.py:56
+#: apps/permission/views.py:68
#, python-brace-format
msgid ""
"You don't have the permission to update this instance of the model "
@@ -1753,7 +1768,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier cette instance du modèle « {model} "
"» avec ces paramètres. Merci de les corriger et de réessayer."
-#: apps/permission/views.py:60
+#: apps/permission/views.py:72
#, python-brace-format
msgid ""
"You don't have the permission to create an instance of the model \"{model}\" "
@@ -1762,11 +1777,11 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » "
"avec ces paramètres. Merci de les corriger et de réessayer."
-#: apps/permission/views.py:96 note_kfet/templates/base.html:106
+#: apps/permission/views.py:108 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Droits"
-#: apps/permission/views.py:101
+#: apps/permission/views.py:113
msgid "All rights"
msgstr "Tous les droits"
@@ -1971,7 +1986,7 @@ msgstr "La remise est déjà fermée."
msgid "You can't change the type of the remittance."
msgstr "Vous ne pouvez pas changer le type de la remise."
-#: apps/treasury/forms.py:123 apps/treasury/models.py:252
+#: apps/treasury/forms.py:123 apps/treasury/models.py:258
#: apps/treasury/tables.py:97 apps/treasury/tables.py:105
#: apps/treasury/templates/treasury/invoice_list.html:16
#: apps/treasury/templates/treasury/remittance_list.html:16
@@ -2003,7 +2018,7 @@ msgstr "Description"
msgid "Address"
msgstr "Adresse"
-#: apps/treasury/models.py:60 apps/treasury/models.py:180
+#: apps/treasury/models.py:60 apps/treasury/models.py:186
msgid "Date"
msgstr "Date"
@@ -2023,7 +2038,7 @@ msgstr "Une facture ne peut plus être modifiée si elle est verrouillée."
msgid "tex source"
msgstr "fichier TeX source"
-#: apps/treasury/models.py:109 apps/treasury/models.py:122
+#: apps/treasury/models.py:109 apps/treasury/models.py:125
msgid "invoice"
msgstr "facture"
@@ -2031,67 +2046,72 @@ msgstr "facture"
msgid "invoices"
msgstr "factures"
-#: apps/treasury/models.py:127
+#: apps/treasury/models.py:113
+#, python-brace-format
+msgid "Invoice #{id}"
+msgstr "Facture n°{id}"
+
+#: apps/treasury/models.py:130
msgid "Designation"
msgstr "Désignation"
-#: apps/treasury/models.py:131
+#: apps/treasury/models.py:134
msgid "Quantity"
msgstr "Quantité"
-#: apps/treasury/models.py:135
+#: apps/treasury/models.py:138
msgid "Unit price"
msgstr "Prix unitaire"
-#: apps/treasury/models.py:151
+#: apps/treasury/models.py:154
msgid "product"
msgstr "produit"
-#: apps/treasury/models.py:152
+#: apps/treasury/models.py:155
msgid "products"
msgstr "produits"
-#: apps/treasury/models.py:169
+#: apps/treasury/models.py:175
msgid "remittance type"
msgstr "type de remise"
-#: apps/treasury/models.py:170
+#: apps/treasury/models.py:176
msgid "remittance types"
msgstr "types de remises"
-#: apps/treasury/models.py:191
+#: apps/treasury/models.py:197
msgid "Comment"
msgstr "Commentaire"
-#: apps/treasury/models.py:196
+#: apps/treasury/models.py:202
msgid "Closed"
msgstr "Fermée"
-#: apps/treasury/models.py:200
+#: apps/treasury/models.py:206
msgid "remittance"
msgstr "remise"
-#: apps/treasury/models.py:201
+#: apps/treasury/models.py:207
msgid "remittances"
msgstr "remises"
-#: apps/treasury/models.py:233
+#: apps/treasury/models.py:239
msgid "Remittance #{:d}: {}"
msgstr "Remise n°{:d} : {}"
-#: apps/treasury/models.py:256
+#: apps/treasury/models.py:262
msgid "special transaction proxy"
msgstr "proxy de transaction spéciale"
-#: apps/treasury/models.py:257
+#: apps/treasury/models.py:263
msgid "special transaction proxies"
msgstr "proxys de transactions spéciales"
-#: apps/treasury/models.py:279
+#: apps/treasury/models.py:288
msgid "credit transaction"
msgstr "transaction de crédit"
-#: apps/treasury/models.py:343
+#: apps/treasury/models.py:352
msgid ""
"This user doesn't have enough money to pay the memberships with its note. "
"Please ask her/him to credit the note before invalidating this credit."
@@ -2099,15 +2119,20 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa "
"note. Merci de lui demander de recharger sa note avant d'invalider ce crédit."
-#: apps/treasury/models.py:355
+#: apps/treasury/models.py:364
#: apps/treasury/templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale"
msgstr "Crédit de la Société générale"
-#: apps/treasury/models.py:356
+#: apps/treasury/models.py:365
msgid "Credits from the Société générale"
msgstr "Crédits de la Société générale"
+#: apps/treasury/models.py:368
+#, python-brace-format
+msgid "Soge credit for {user}"
+msgstr "Crédit de la société générale pour l'utilisateur {user}"
+
#: apps/treasury/tables.py:20
msgid "Invoice #{:d}"
msgstr "Facture n°{:d}"
From 353416618a238962bb8032f0e5eff9b5a184bc14 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 13:54:06 +0200
Subject: [PATCH 18/23] Linebreaks are rendered as < > in the wiki
---
apps/scripts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/scripts b/apps/scripts
index 4506dd4d..e5b76b7c 160000
--- a/apps/scripts
+++ b/apps/scripts
@@ -1 +1 @@
-Subproject commit 4506dd4dc09a1255e68043b2c13afff7b3b72fce
+Subproject commit e5b76b7c35592aba4225115f933f2a7ed3a66df3
From 78586b934322fe020eb3ebf5211738d5d269c04a Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 14:52:37 +0200
Subject: [PATCH 19/23] Don't trigger signals when we add an object through a
permission check
---
apps/logs/signals.py | 4 ++--
apps/member/signals.py | 2 +-
apps/note/signals.py | 20 ++++++++++----------
apps/permission/models.py | 4 ++--
apps/permission/signals.py | 5 +++--
apps/treasury/signals.py | 13 +++++++------
6 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/apps/logs/signals.py b/apps/logs/signals.py
index f313cc5b..b0b4d2c2 100644
--- a/apps/logs/signals.py
+++ b/apps/logs/signals.py
@@ -50,7 +50,7 @@ def save_object(sender, instance, **kwargs):
in order to store each modification made
"""
# noinspection PyProtectedMember
- if instance._meta.label_lower in EXCLUDED or hasattr(instance, "_no_log"):
+ if instance._meta.label_lower in EXCLUDED or hasattr(instance, "_no_signal"):
return
# noinspection PyProtectedMember
@@ -117,7 +117,7 @@ def delete_object(sender, instance, **kwargs):
Each time a model is deleted, an entry in the table `Changelog` is added in the database
"""
# noinspection PyProtectedMember
- if instance._meta.label_lower in EXCLUDED or hasattr(instance, "_no_log"):
+ if instance._meta.label_lower in EXCLUDED or hasattr(instance, "_no_signal"):
return
# Si un utilisateur est connecté, on récupère l'utilisateur courant ainsi que son adresse IP
diff --git a/apps/member/signals.py b/apps/member/signals.py
index 43659b01..d590f446 100644
--- a/apps/member/signals.py
+++ b/apps/member/signals.py
@@ -6,7 +6,7 @@ def save_user_profile(instance, created, raw, **_kwargs):
"""
Hook to create and save a profile when an user is updated if it is not registered with the signup form
"""
- if not raw and created and instance.is_active:
+ if not raw and created and instance.is_active and not hasattr(instance, "_no_signal"):
from .models import Profile
Profile.objects.get_or_create(user=instance)
if instance.is_superuser:
diff --git a/apps/note/signals.py b/apps/note/signals.py
index 51ed92d8..c1545ec2 100644
--- a/apps/note/signals.py
+++ b/apps/note/signals.py
@@ -6,7 +6,8 @@ def save_user_note(instance, raw, **_kwargs):
"""
Hook to create and save a note when an user is updated
"""
- if not raw and (instance.is_superuser or instance.profile.registration_valid):
+ if not raw and (instance.is_superuser or instance.profile.registration_valid)\
+ and not hasattr(instance, "_no_signal"):
# Create note only when the registration is validated
from note.models import NoteUser
NoteUser.objects.get_or_create(user=instance)
@@ -17,18 +18,17 @@ def save_club_note(instance, raw, **_kwargs):
"""
Hook to create and save a note when a club is updated
"""
- if raw:
- # When provisionning data, do not try to autocreate
- return
-
- from .models import NoteClub
- NoteClub.objects.get_or_create(club=instance)
- instance.note.save()
+ # When provisionning data, do not try to autocreate
+ if not raw and not hasattr(instance, "_no_signal"):
+ from .models import NoteClub
+ NoteClub.objects.get_or_create(club=instance)
+ instance.note.save()
def delete_transaction(instance, **_kwargs):
"""
Whenever we want to delete a transaction (caution with this), we ensure the transaction is invalid first.
"""
- instance.valid = False
- instance.save()
+ if not hasattr(instance, "_no_signal"):
+ instance.valid = False
+ instance.save()
diff --git a/apps/permission/models.py b/apps/permission/models.py
index 3d395a75..ae77e1a0 100644
--- a/apps/permission/models.py
+++ b/apps/permission/models.py
@@ -57,8 +57,8 @@ class InstancedPermission:
# Force insertion, no data verification, no trigger
obj._force_save = True
- # We don't want log anything
- obj._no_log = True
+ # We don't want to trigger any signal (log, ...)
+ obj.no_signal = True
Model.save(obj, force_insert=True)
ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
# Delete testing object
diff --git a/apps/permission/signals.py b/apps/permission/signals.py
index 112247eb..e738545a 100644
--- a/apps/permission/signals.py
+++ b/apps/permission/signals.py
@@ -28,7 +28,7 @@ def pre_save_object(sender, instance, **kwargs):
if instance._meta.label_lower in EXCLUDED:
return
- if hasattr(instance, "_force_save"):
+ if hasattr(instance, "_force_save") or hasattr(instance, "_no_signal"):
return
user = get_current_authenticated_user()
@@ -82,7 +82,8 @@ def pre_delete_object(instance, **kwargs):
if instance._meta.label_lower in EXCLUDED:
return
- if hasattr(instance, "_force_delete") or hasattr(instance, "pk") and instance.pk == 0:
+ if hasattr(instance, "_force_delete") or hasattr(instance, "pk") and instance.pk == 0 \
+ or hasattr(instance, "_no_signal"):
# Don't check permissions on force-deleted objects
return
diff --git a/apps/treasury/signals.py b/apps/treasury/signals.py
index b7038ab6..f08540d1 100644
--- a/apps/treasury/signals.py
+++ b/apps/treasury/signals.py
@@ -9,9 +9,10 @@ def save_special_transaction(instance, created, **kwargs):
When a special transaction is created, we create its linked proxy
"""
- if instance.is_credit():
- if created and RemittanceType.objects.filter(note=instance.source).exists():
- SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
- else:
- if created and RemittanceType.objects.filter(note=instance.destination).exists():
- SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
+ if not hasattr(instance, "_no_signal"):
+ if instance.is_credit():
+ if created and RemittanceType.objects.filter(note=instance.source).exists():
+ SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
+ else:
+ if created and RemittanceType.objects.filter(note=instance.destination).exists():
+ SpecialTransactionProxy.objects.create(transaction=instance, remittance=None).save()
From 346aa94ead306f32e3b6faefdfe0dd4673e46376 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 14:57:30 +0200
Subject: [PATCH 20/23] Don't trigger signals when we add an object through a
permission check
---
apps/permission/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/permission/models.py b/apps/permission/models.py
index ae77e1a0..ff348404 100644
--- a/apps/permission/models.py
+++ b/apps/permission/models.py
@@ -58,7 +58,7 @@ class InstancedPermission:
# Force insertion, no data verification, no trigger
obj._force_save = True
# We don't want to trigger any signal (log, ...)
- obj.no_signal = True
+ obj._no_signal = True
Model.save(obj, force_insert=True)
ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
# Delete testing object
From 6b068536781617a18536c5ff729480f1e0626867 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Mon, 7 Sep 2020 19:28:18 +0200
Subject: [PATCH 21/23] Add cards to registration apps
---
.../email_validation_complete.html | 25 +++++++++++++++----
.../email_validation_email_sent.html | 24 ++++++++++--------
2 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/apps/registration/templates/registration/email_validation_complete.html b/apps/registration/templates/registration/email_validation_complete.html
index dca26470..11a84fe9 100644
--- a/apps/registration/templates/registration/email_validation_complete.html
+++ b/apps/registration/templates/registration/email_validation_complete.html
@@ -5,14 +5,29 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% load i18n %}
{% block content %}
- {% if validlink %}
- {% trans "Your email have successfully been validated." %}
+
+
+
+ {% if validlink %}
+
+ {% trans "Your email have successfully been validated." %}
+
{% if user_object.profile.registration_valid %}
+
{% blocktrans %}You can now log in .{% endblocktrans %}
+
{% else %}
+
{% trans "You must pay now your membership in the Kfet to complete your registration." %}
+
{% endif %}
- {% else %}
- {% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %}
- {% endif %}
+ {% else %}
+
+ {% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %}
+
+ {% endif %}
+
+
{% endblock %}
diff --git a/apps/registration/templates/registration/email_validation_email_sent.html b/apps/registration/templates/registration/email_validation_email_sent.html
index 627c864b..87691670 100644
--- a/apps/registration/templates/registration/email_validation_email_sent.html
+++ b/apps/registration/templates/registration/email_validation_email_sent.html
@@ -5,13 +5,17 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% load i18n %}
{% block content %}
-{% trans "Account activation" %}
-
-
- {% trans "An email has been sent. Please click on the link to activate your account." %}
-
-
-
- {% trans "You must also go to the Kfet to pay your membership. The WEI registration includes the BDE membership." %}
-
-{% endblock %}
\ No newline at end of file
+
+
+
+
+ {% trans "An email has been sent. Please click on the link to activate your account." %}
+
+
+ {% trans "You must also go to the Kfet to pay your membership. The WEI registration includes the BDE membership." %}
+
+
+
+{% endblock %}
From dc6a5f56f6893a81a0823117d7a4c108485b9290 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss
Date: Mon, 7 Sep 2020 19:44:54 +0200
Subject: [PATCH 22/23] Remove WEI mention from register page and mail
---
.../email_validation_email_sent.html | 2 +-
.../mails/email_validation_email.html | 4 +-
.../mails/email_validation_email.txt | 4 +-
locale/de/LC_MESSAGES/django.po | 55 ++++++++-----------
locale/fr/LC_MESSAGES/django.po | 45 +++++++--------
5 files changed, 49 insertions(+), 61 deletions(-)
diff --git a/apps/registration/templates/registration/email_validation_email_sent.html b/apps/registration/templates/registration/email_validation_email_sent.html
index 87691670..f6db4cac 100644
--- a/apps/registration/templates/registration/email_validation_email_sent.html
+++ b/apps/registration/templates/registration/email_validation_email_sent.html
@@ -14,7 +14,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% trans "An email has been sent. Please click on the link to activate your account." %}
- {% trans "You must also go to the Kfet to pay your membership. The WEI registration includes the BDE membership." %}
+ {% trans "You must also go to the Kfet to pay your membership." %}
diff --git a/apps/registration/templates/registration/mails/email_validation_email.html b/apps/registration/templates/registration/mails/email_validation_email.html
index 0d5b41f5..40d246c9 100644
--- a/apps/registration/templates/registration/mails/email_validation_email.html
+++ b/apps/registration/templates/registration/mails/email_validation_email.html
@@ -27,7 +27,7 @@
- {% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet. Note that the WEI registration includes the Kfet membership." %}
+ {% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %}
@@ -38,4 +38,4 @@
{% trans "The Note Kfet team." %}
{% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %}
-
\ No newline at end of file
+
diff --git a/apps/registration/templates/registration/mails/email_validation_email.txt b/apps/registration/templates/registration/mails/email_validation_email.txt
index 5ce48110..7b280bb2 100644
--- a/apps/registration/templates/registration/mails/email_validation_email.txt
+++ b/apps/registration/templates/registration/mails/email_validation_email.txt
@@ -8,9 +8,9 @@ https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=toke
{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %}
-{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet. Note that the WEI registration includes the Kfet membership." %}
+{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %}
{% trans "Thanks" %},
{% trans "The Note Kfet team." %}
-{% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %}
\ No newline at end of file
+{% trans "Mail generated by the Note Kfet on the" %} {% now "j F Y à H:i:s" %}
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index c3bed92d..3891a934 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-07 11:14+0200\n"
+"POT-Creation-Date: 2020-09-07 19:43+0200\n"
"PO-Revision-Date: 2020-09-03 23:47+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -187,10 +187,9 @@ msgid "Entry for {guest}, invited by {note} to the activity {activity}"
msgstr "Eintritt für {guest}, von {note} zur Vanstaltung {activity} eingeladen"
#: apps/activity/models.py:194
-#, fuzzy, python-brace-format
-#| msgid "Entry for activity \"{}\""
+#, python-brace-format
msgid "Entry for {note} to the activity {activity}"
-msgstr "Eintritt zur Veranstaltung \"{}\""
+msgstr "Eintritt von {note} zur Veranstaltung {activity}"
#: apps/activity/models.py:201
msgid "Already entered on "
@@ -1494,7 +1493,8 @@ msgstr "Verlauf der letzten Transaktionen"
#: apps/note/templates/note/mails/negative_balance.txt:25
#: apps/note/templates/note/mails/negative_notes_report.html:46
#: apps/note/templates/note/mails/negative_notes_report.txt:13
-#: apps/note/templates/note/mails/weekly_report.html:54
+#: apps/note/templates/note/mails/weekly_report.html:51
+#: apps/note/templates/note/mails/weekly_report.txt:32
#: apps/registration/templates/registration/mails/email_validation_email.html:40
#: apps/registration/templates/registration/mails/email_validation_email.txt:16
msgid "Mail generated by the Note Kfet on the"
@@ -1694,7 +1694,7 @@ msgstr ""
"Sie haben nicht die Berechtigung, das Feld {field} in dieser Instanz von "
"Modell {app_label} zu ändern. {model_name}"
-#: apps/permission/signals.py:73 apps/permission/views.py:101
+#: apps/permission/signals.py:73 apps/permission/views.py:89
#, python-brace-format
msgid ""
"You don't have the permission to add an instance of model {app_label}."
@@ -1703,7 +1703,7 @@ msgstr ""
"Sie haben nicht die Berechtigung, eine Instanz von model {app_label}. "
"{model_name} hinzufügen."
-#: apps/permission/signals.py:101
+#: apps/permission/signals.py:102
#, python-brace-format
msgid ""
"You don't have the permission to delete this instance of model {app_label}."
@@ -1752,7 +1752,7 @@ msgstr "Abfrage:"
msgid "No associated permission"
msgstr "Keine zugehörige Berechtigung"
-#: apps/permission/views.py:68
+#: apps/permission/views.py:56
#, python-brace-format
msgid ""
"You don't have the permission to update this instance of the model "
@@ -1762,7 +1762,7 @@ msgstr ""
"diesen Parametern zu aktualisieren. Bitte korrigieren Sie Ihre Daten und "
"versuchen Sie es erneut."
-#: apps/permission/views.py:72
+#: apps/permission/views.py:60
#, python-brace-format
msgid ""
"You don't have the permission to create an instance of the model \"{model}\" "
@@ -1772,11 +1772,11 @@ msgstr ""
"diesen Parametern zu erstellen. Bitte korrigieren Sie Ihre Daten und "
"versuchen Sie es erneut."
-#: apps/permission/views.py:108 note_kfet/templates/base.html:106
+#: apps/permission/views.py:96 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Rechten"
-#: apps/permission/views.py:113
+#: apps/permission/views.py:101
msgid "All rights"
msgstr "Alle Rechten"
@@ -1809,23 +1809,23 @@ msgstr "BDE Mitglieder werden"
msgid "Join Kfet Club"
msgstr "Kfet Mitglieder werden"
-#: apps/registration/templates/registration/email_validation_complete.html:9
+#: apps/registration/templates/registration/email_validation_complete.html:15
msgid "Your email have successfully been validated."
msgstr "Ihre E-Mail wurde erfolgreich validiert."
-#: apps/registration/templates/registration/email_validation_complete.html:11
+#: apps/registration/templates/registration/email_validation_complete.html:19
#, python-format
msgid "You can now log in ."
msgstr "Sie können sich jetz anmelden ."
-#: apps/registration/templates/registration/email_validation_complete.html:13
+#: apps/registration/templates/registration/email_validation_complete.html:23
msgid ""
"You must pay now your membership in the Kfet to complete your registration."
msgstr ""
"Sie müssen jetzt Ihre Mitgliedschaft im Kfet bezahlen, um Ihre Registrierung "
"abzuschließen."
-#: apps/registration/templates/registration/email_validation_complete.html:16
+#: apps/registration/templates/registration/email_validation_complete.html:28
msgid ""
"The link was invalid. The token may have expired. Please send us an email to "
"activate your account."
@@ -1833,24 +1833,20 @@ msgstr ""
"Der Link war ungültig. Das Token ist möglicherweise abgelaufen. Bitte senden "
"Sie uns eine E-Mail, um Ihr Konto zu aktivieren."
-#: apps/registration/templates/registration/email_validation_email_sent.html:8
+#: apps/registration/templates/registration/email_validation_email_sent.html:10
msgid "Account activation"
msgstr "Kontoaktivierung"
-#: apps/registration/templates/registration/email_validation_email_sent.html:11
+#: apps/registration/templates/registration/email_validation_email_sent.html:14
msgid ""
"An email has been sent. Please click on the link to activate your account."
msgstr ""
"Eine E-Mail wurde gesendet. Bitte klicken Sie auf den Link, um Ihr Konto zu "
"aktivieren."
-#: apps/registration/templates/registration/email_validation_email_sent.html:15
-msgid ""
-"You must also go to the Kfet to pay your membership. The WEI registration "
-"includes the BDE membership."
-msgstr ""
-"Sie müssen auch zum Kfet gehen, um Ihre Mitgliedschaft zu bezahlen. Die WEI-"
-"Registrierung beinhaltet die BDE-Mitgliedschaft."
+#: apps/registration/templates/registration/email_validation_email_sent.html:17
+msgid "You must also go to the Kfet to pay your membership."
+msgstr "Sie müssen auch zum Kfet gehen, um Ihre Mitgliedschaft zu bezahlen."
#: apps/registration/templates/registration/future_profile_detail.html:49
#: apps/wei/templates/wei/weiregistration_confirm_delete.html:11
@@ -1898,12 +1894,10 @@ msgstr ""
#: apps/registration/templates/registration/mails/email_validation_email.txt:11
msgid ""
"After that, you'll have to wait that someone validates your account before "
-"you can log in. You will need to pay your membership in the Kfet. Note that "
-"the WEI registration includes the Kfet membership."
+"you can log in. You will need to pay your membership in the Kfet."
msgstr ""
"Danach müssen Sie warten, bis jemand Ihr Konto validiert, bevor Sie sich "
-"anmelden können. Sie müssen Ihre Mitgliedschaft im Kfet bezahlen. Beachten "
-"Sie, dass die WEI-Registrierung die Kfet-Mitgliedschaft enthält."
+"anmelden können. Sie müssen Ihre Mitgliedschaft im Kfet bezahlen."
#: apps/registration/templates/registration/mails/email_validation_email.html:34
#: apps/registration/templates/registration/mails/email_validation_email.txt:13
@@ -2044,10 +2038,9 @@ msgid "invoices"
msgstr "Rechnungen"
#: apps/treasury/models.py:113
-#, fuzzy, python-brace-format
-#| msgid "Invoice #{:d}"
+#, python-brace-format
msgid "Invoice #{id}"
-msgstr "Rechnung #{:d}"
+msgstr "Rechnung #{id}"
#: apps/treasury/models.py:130
msgid "Designation"
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 7c2ee43b..5e6e2740 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-07 11:14+0200\n"
+"POT-Creation-Date: 2020-09-07 19:43+0200\n"
"PO-Revision-Date: 2020-09-02 23:18+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -1498,7 +1498,8 @@ msgstr "Historique des transactions récentes"
#: apps/note/templates/note/mails/negative_balance.txt:25
#: apps/note/templates/note/mails/negative_notes_report.html:46
#: apps/note/templates/note/mails/negative_notes_report.txt:13
-#: apps/note/templates/note/mails/weekly_report.html:54
+#: apps/note/templates/note/mails/weekly_report.html:51
+#: apps/note/templates/note/mails/weekly_report.txt:32
#: apps/registration/templates/registration/mails/email_validation_email.html:40
#: apps/registration/templates/registration/mails/email_validation_email.txt:16
msgid "Mail generated by the Note Kfet on the"
@@ -1700,7 +1701,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}."
-#: apps/permission/signals.py:73 apps/permission/views.py:101
+#: apps/permission/signals.py:73 apps/permission/views.py:89
#, python-brace-format
msgid ""
"You don't have the permission to add an instance of model {app_label}."
@@ -1709,7 +1710,7 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}."
"{model_name}."
-#: apps/permission/signals.py:101
+#: apps/permission/signals.py:102
#, python-brace-format
msgid ""
"You don't have the permission to delete this instance of model {app_label}."
@@ -1759,7 +1760,7 @@ msgstr "Requête :"
msgid "No associated permission"
msgstr "Pas de permission associée"
-#: apps/permission/views.py:68
+#: apps/permission/views.py:56
#, python-brace-format
msgid ""
"You don't have the permission to update this instance of the model "
@@ -1768,7 +1769,7 @@ msgstr ""
"Vous n'avez pas la permission de modifier cette instance du modèle « {model} "
"» avec ces paramètres. Merci de les corriger et de réessayer."
-#: apps/permission/views.py:72
+#: apps/permission/views.py:60
#, python-brace-format
msgid ""
"You don't have the permission to create an instance of the model \"{model}\" "
@@ -1777,11 +1778,11 @@ msgstr ""
"Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » "
"avec ces paramètres. Merci de les corriger et de réessayer."
-#: apps/permission/views.py:108 note_kfet/templates/base.html:106
+#: apps/permission/views.py:96 note_kfet/templates/base.html:106
msgid "Rights"
msgstr "Droits"
-#: apps/permission/views.py:113
+#: apps/permission/views.py:101
msgid "All rights"
msgstr "Tous les droits"
@@ -1814,23 +1815,23 @@ msgstr "Adhérer au club BDE"
msgid "Join Kfet Club"
msgstr "Adhérer au club Kfet"
-#: apps/registration/templates/registration/email_validation_complete.html:9
+#: apps/registration/templates/registration/email_validation_complete.html:15
msgid "Your email have successfully been validated."
msgstr "Votre adresse e-mail a bien été validée."
-#: apps/registration/templates/registration/email_validation_complete.html:11
+#: apps/registration/templates/registration/email_validation_complete.html:19
#, python-format
msgid "You can now log in ."
msgstr "Vous pouvez désormais vous connecter ."
-#: apps/registration/templates/registration/email_validation_complete.html:13
+#: apps/registration/templates/registration/email_validation_complete.html:23
msgid ""
"You must pay now your membership in the Kfet to complete your registration."
msgstr ""
"Vous devez désormais payer votre adhésion à la Kfet pour compléter votre "
"inscription."
-#: apps/registration/templates/registration/email_validation_complete.html:16
+#: apps/registration/templates/registration/email_validation_complete.html:28
msgid ""
"The link was invalid. The token may have expired. Please send us an email to "
"activate your account."
@@ -1838,24 +1839,20 @@ msgstr ""
"Le lien est invalide. Le jeton a sans doute expiré. Merci de nous contacter "
"pour activer votre compte."
-#: apps/registration/templates/registration/email_validation_email_sent.html:8
+#: apps/registration/templates/registration/email_validation_email_sent.html:10
msgid "Account activation"
msgstr "Activation du compte"
-#: apps/registration/templates/registration/email_validation_email_sent.html:11
+#: apps/registration/templates/registration/email_validation_email_sent.html:14
msgid ""
"An email has been sent. Please click on the link to activate your account."
msgstr ""
"Un email vient de vous être envoyé. Merci de cliquer sur le lien de "
"validation pour activer votre compte."
-#: apps/registration/templates/registration/email_validation_email_sent.html:15
-msgid ""
-"You must also go to the Kfet to pay your membership. The WEI registration "
-"includes the BDE membership."
-msgstr ""
-"Vous devrez également vous rendre à la Kfet pour payer votre adhésion. "
-"L'inscription au WEI inclut l'adhésion au BDE."
+#: apps/registration/templates/registration/email_validation_email_sent.html:17
+msgid "You must also go to the Kfet to pay your membership."
+msgstr "Vous devrez également vous rendre à la Kfet pour payer votre adhésion."
#: apps/registration/templates/registration/future_profile_detail.html:49
#: apps/wei/templates/wei/weiregistration_confirm_delete.html:11
@@ -1901,12 +1898,10 @@ msgstr "Ce lien n'est valide que pendant quelques jours."
#: apps/registration/templates/registration/mails/email_validation_email.txt:11
msgid ""
"After that, you'll have to wait that someone validates your account before "
-"you can log in. You will need to pay your membership in the Kfet. Note that "
-"the WEI registration includes the Kfet membership."
+"you can log in. You will need to pay your membership in the Kfet."
msgstr ""
"Après cela, vous devrez attendre que quelqu'un valide votre compte avant de "
-"pouvoir vous connecter. Vous devrez payer votre adhésion à la Kfet. Notez "
-"que l'adhésion Kfet est incluse dans l'inscription au WEI."
+"pouvoir vous connecter. Vous devrez payer votre adhésion à la Kfet."
#: apps/registration/templates/registration/mails/email_validation_email.html:34
#: apps/registration/templates/registration/mails/email_validation_email.txt:13
From fa3c723140cb5de07d95fa8eb8ca74fdbed667d0 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO
Date: Mon, 7 Sep 2020 21:33:23 +0200
Subject: [PATCH 23/23] =?UTF-8?q?The=20BDE=20offers=2080=20=E2=82=AC=20to?=
=?UTF-8?q?=20each=20new=20member=20that=20registers=20to=20the=20Soci?=
=?UTF-8?q?=C3=A9t=C3=A9=20g=C3=A9n=C3=A9rale?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../migrations/0003_create_bde_and_kfet.py | 4 +-
apps/member/views.py | 2 +-
apps/note/models/transactions.py | 2 +-
apps/permission/views.py | 16 ++++++-
apps/registration/tests/test_registration.py | 2 +-
apps/registration/views.py | 9 ++++
apps/treasury/models.py | 45 ++++++++++++-------
.../templates/treasury/sogecredit_list.html | 2 +-
apps/treasury/tests/test_treasury.py | 3 +-
apps/treasury/views.py | 7 +--
10 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/apps/member/migrations/0003_create_bde_and_kfet.py b/apps/member/migrations/0003_create_bde_and_kfet.py
index 0464569f..5f218040 100644
--- a/apps/member/migrations/0003_create_bde_and_kfet.py
+++ b/apps/member/migrations/0003_create_bde_and_kfet.py
@@ -27,8 +27,8 @@ def create_bde_and_kfet(apps, schema_editor):
parent_club_id=1,
email="tresorerie.bde@example.com",
require_memberships=True,
- membership_fee_paid=500,
- membership_fee_unpaid=500,
+ membership_fee_paid=3500,
+ membership_fee_unpaid=3500,
membership_duration=396,
membership_start="2020-08-01",
membership_end="2021-09-30",
diff --git a/apps/member/views.py b/apps/member/views.py
index d0ae106a..033533ff 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -138,7 +138,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
We can't display information of a not registered user.
"""
- return super().get_queryset().filter(profile__registration_valid=True)
+ return super().get_queryset(**kwargs).filter(profile__registration_valid=True)
def get_context_data(self, **kwargs):
"""
diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index b89b405f..c28d66da 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -175,7 +175,7 @@ class Transaction(PolymorphicModel):
created = self.pk is None
to_transfer = self.amount * self.quantity
- if not created:
+ if not created and not self.valid and not hasattr(self, "_force_save"):
# Revert old transaction
old_transaction = Transaction.objects.get(pk=self.pk)
# Check that nothing important changed
diff --git a/apps/permission/views.py b/apps/permission/views.py
index 70aa7184..343152f5 100644
--- a/apps/permission/views.py
+++ b/apps/permission/views.py
@@ -8,6 +8,7 @@ from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.forms import HiddenInput
+from django.http import Http404
from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView, TemplateView, CreateView
from member.models import Membership
@@ -24,9 +25,20 @@ class ProtectQuerysetMixin:
Display 404 error if the user can't see an object, remove the fields the user can't
update on an update form (useful if the user can't change only specified fields).
"""
- def get_queryset(self, **kwargs):
+ def get_queryset(self, filter_permissions=True, **kwargs):
qs = super().get_queryset(**kwargs)
- return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view")).distinct()
+ return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view")).distinct()\
+ if filter_permissions else qs
+
+ def get_object(self, queryset=None):
+ try:
+ return super().get_object(queryset)
+ except Http404 as e:
+ try:
+ super().get_object(self.get_queryset(filter_permissions=False))
+ raise PermissionDenied()
+ except Http404:
+ raise e
def get_form(self, form_class=None):
form = super().get_form(form_class)
diff --git a/apps/registration/tests/test_registration.py b/apps/registration/tests/test_registration.py
index e2191445..adb773f9 100644
--- a/apps/registration/tests/test_registration.py
+++ b/apps/registration/tests/test_registration.py
@@ -364,7 +364,7 @@ class TestValidateRegistration(TestCase):
self.assertTrue(Membership.objects.filter(club__name="Kfet", user=self.user).exists())
self.assertTrue(SogeCredit.objects.filter(user=self.user).exists())
self.assertEqual(Transaction.objects.filter(
- Q(source=self.user.note) | Q(destination=self.user.note)).count(), 2)
+ Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
self.assertFalse(Transaction.objects.filter(valid=True).exists())
response = self.client.get(self.user.profile.get_absolute_url())
diff --git a/apps/registration/views.py b/apps/registration/views.py
index 7a924591..1f71931e 100644
--- a/apps/registration/views.py
+++ b/apps/registration/views.py
@@ -21,6 +21,7 @@ from note.templatetags.pretty_money import pretty_money
from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin
+from treasury.models import SogeCredit
from .forms import SignUpForm, ValidationForm
from .tables import FutureUserTable
@@ -219,6 +220,9 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid
kfet = Club.objects.get(name="Kfet")
fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
+ # In 2020, for COVID-19 reasons, the BDE offered 80 € to each new member that opens a Sogé account,
+ # since there is no WEI.
+ fee += 8000
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
return ctx
@@ -342,6 +346,11 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
membership.roles.add(Role.objects.get(name="Adhérent Kfet"))
membership.save()
+ if soge:
+ soge_credit = SogeCredit.objects.get(user=user)
+ # Update the credit transaction amount
+ soge_credit.save()
+
return ret
def get_success_url(self):
diff --git a/apps/treasury/models.py b/apps/treasury/models.py
index 175829fe..d611650f 100644
--- a/apps/treasury/models.py
+++ b/apps/treasury/models.py
@@ -291,11 +291,11 @@ class SogeCredit(models.Model):
@property
def valid(self):
- return self.credit_transaction is not None
+ return self.credit_transaction.valid
@property
def amount(self):
- return sum(transaction.total for transaction in self.transactions.all())
+ return sum(transaction.total for transaction in self.transactions.all()) + 8000
def invalidate(self):
"""
@@ -304,11 +304,7 @@ class SogeCredit(models.Model):
"""
if self.valid:
self.credit_transaction.valid = False
- self.credit_transaction._force_save = True
self.credit_transaction.save()
- self.credit_transaction._force_delete = True
- self.credit_transaction.delete()
- self.credit_transaction = None
for transaction in self.transactions.all():
transaction.valid = False
transaction._force_save = True
@@ -321,17 +317,10 @@ class SogeCredit(models.Model):
# First invalidate all transaction and delete the credit if already did (and force mode)
self.invalidate()
- self.credit_transaction = SpecialTransaction.objects.create(
- source=NoteSpecial.objects.get(special_type="Virement bancaire"),
- destination=self.user.note,
- quantity=1,
- amount=self.amount,
- reason="Crédit société générale",
- last_name=self.user.last_name,
- first_name=self.user.first_name,
- bank="Société générale",
- created_at=self.transactions.order_by("-created_at").first().created_at,
- )
+ # Refresh credit amount
+ self.save()
+ self.credit_transaction.valid = True
+ self.credit_transaction.save()
self.save()
for transaction in self.transactions.all():
@@ -340,6 +329,25 @@ class SogeCredit(models.Model):
transaction.created_at = timezone.now()
transaction.save()
+ def save(self, *args, **kwargs):
+ if not self.credit_transaction:
+ self.credit_transaction = SpecialTransaction.objects.create(
+ source=NoteSpecial.objects.get(special_type="Virement bancaire"),
+ destination=self.user.note,
+ quantity=1,
+ amount=0,
+ reason="Crédit société générale",
+ last_name=self.user.last_name,
+ first_name=self.user.first_name,
+ bank="Société générale",
+ valid=False,
+ )
+ elif not self.valid:
+ self.credit_transaction.amount = self.amount
+ self.credit_transaction._force_save = True
+ self.credit_transaction.save()
+ super().save(*args, **kwargs)
+
def delete(self, **kwargs):
"""
Deleting a SogeCredit is equivalent to say that the Société générale didn't pay.
@@ -358,6 +366,9 @@ class SogeCredit(models.Model):
transaction.valid = True
transaction.created_at = timezone.now()
transaction.save()
+ self.credit_transaction.valid = False
+ self.credit_transaction.reason += " (invalide)"
+ self.credit_transaction.save()
super().delete(**kwargs)
class Meta:
diff --git a/apps/treasury/templates/treasury/sogecredit_list.html b/apps/treasury/templates/treasury/sogecredit_list.html
index 1eb1aba5..c561da72 100644
--- a/apps/treasury/templates/treasury/sogecredit_list.html
+++ b/apps/treasury/templates/treasury/sogecredit_list.html
@@ -30,7 +30,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
-
+
{% trans "Filter with unvalidated credits only" %}
diff --git a/apps/treasury/tests/test_treasury.py b/apps/treasury/tests/test_treasury.py
index 0d6e5d62..505453b9 100644
--- a/apps/treasury/tests/test_treasury.py
+++ b/apps/treasury/tests/test_treasury.py
@@ -353,7 +353,6 @@ class TestSogeCredits(TestCase):
soge_credit.refresh_from_db()
self.assertTrue(soge_credit.valid)
self.user.note.refresh_from_db()
- self.assertEqual(self.user.note.balance, 0)
self.assertEqual(
Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
self.assertTrue(self.user.profile.soge)
@@ -391,7 +390,7 @@ class TestSogeCredits(TestCase):
self.user.note.refresh_from_db()
self.assertEqual(self.user.note.balance, 0)
self.assertEqual(
- Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
+ Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 4)
self.assertFalse(self.user.profile.soge)
def test_invoice_api(self):
diff --git a/apps/treasury/views.py b/apps/treasury/views.py
index a8e03cbe..ecefc5cf 100644
--- a/apps/treasury/views.py
+++ b/apps/treasury/views.py
@@ -425,11 +425,8 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
)
- if "valid" in self.request.GET:
- q = Q(credit_transaction=None)
- if not self.request.GET["valid"]:
- q = ~q
- qs = qs.filter(q)
+ if "valid" not in self.request.GET or not self.request.GET["valid"]:
+ qs = qs.filter(credit_transaction__valid=False)
return qs[:20]