1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-02-24 17:11:18 +00:00

Compare commits

..

No commits in common. "4e1ba1447a37138d8caa2f2107d7cd3e0b0ecb24" and "f25eb1d2c5d972bc2ed39f0d078a0944e297c7aa" have entirely different histories.

11 changed files with 140 additions and 330 deletions

View File

@ -1,6 +1,6 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.db import transaction
from rest_framework import serializers
from note.api.serializers import SpecialTransactionSerializer
@ -68,14 +68,6 @@ class SogeCreditSerializer(serializers.ModelSerializer):
The djangorestframework plugin will analyse the model `SogeCredit` and parse all fields in the API.
"""
@transaction.atomic
def save(self, **kwargs):
# Update soge transactions after creating a credit
instance = super().save(**kwargs)
instance.update_transactions()
instance.save()
return instance
class Meta:
model = SogeCredit
fields = '__all__'

View File

@ -4,12 +4,11 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django import forms
from django.contrib.auth.models import User
from django.db import transaction
from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import AmountInput, Autocomplete
from note_kfet.inputs import AmountInput
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
class InvoiceForm(forms.ModelForm):
@ -162,19 +161,3 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
class Meta:
model = SpecialTransactionProxy
fields = ('remittance', )
class SogeCreditForm(forms.ModelForm):
class Meta:
model = SogeCredit
fields = ('user', )
widgets = {
"user": Autocomplete(
User,
attrs={
'api_url': '/api/user/',
'name_field': 'username',
'placeholder': 'Nom ...',
},
),
}

View File

@ -11,10 +11,7 @@ from django.db.models import Q
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from member.models import Club, Membership
from note.models import NoteSpecial, SpecialTransaction, MembershipTransaction, NoteUser
from wei.models import WEIClub
class Invoice(models.Model):
@ -289,7 +286,6 @@ class SogeCredit(models.Model):
transactions = models.ManyToManyField(
MembershipTransaction,
related_name="+",
blank=True,
verbose_name=_("membership transactions"),
)
@ -309,40 +305,6 @@ class SogeCredit(models.Model):
return self.credit_transaction.total if self.valid \
else sum(transaction.total for transaction in self.transactions.all())
def update_transactions(self):
"""
The Sogé credit may be created after the user already paid its memberships.
We query transactions and update the credit, if it is unvalid.
"""
if self.valid or not self.pk:
return
bde = Club.objects.get(name="BDE")
kfet = Club.objects.get(name="Kfet")
wei = WEIClub.objects.order_by('-year').first()
bde_qs = Membership.objects.filter(user=self.user, club=bde, date_start__gte=bde.membership_start)
kfet_qs = Membership.objects.filter(user=self.user, club=kfet, date_start__gte=kfet.membership_start)
wei_qs = Membership.objects.filter(user=self.user, club=wei, date_start__gte=wei.membership_start)
if bde_qs.exists():
m = bde_qs.get()
if m.transaction not in self.transactions.all():
self.transactions.add(m.transaction)
if kfet_qs.exists():
m = kfet_qs.get()
if m.transaction not in self.transactions.all():
self.transactions.add(m.transaction)
if wei_qs.exists():
m = wei_qs.get()
if m.transaction not in self.transactions.all():
self.transactions.add(m.transaction)
for tr in self.transactions.all():
tr.valid = False
tr.save()
def invalidate(self):
"""
Invalidating a Société générale delete the transaction of the bank if it was already created.
@ -403,8 +365,7 @@ class SogeCredit(models.Model):
self.credit_transaction.amount = self.amount
self.credit_transaction._force_save = True
self.credit_transaction.save()
return super().save(*args, **kwargs)
super().save(*args, **kwargs)
def delete(self, **kwargs):
"""

View File

@ -3,7 +3,6 @@
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load render_table from django_tables2 %}
{% load crispy_forms_filters %}
{% load i18n %}
{% block content %}
@ -28,12 +27,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ title }}
</h3>
<div class="card-body">
<div class="input-group">
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
<div class="input-group-append">
<button id="add_sogecredit" class="btn btn-success" data-toggle="modal" data-target="#add-sogecredit-modal">{% trans "Add" %}</button>
</div>
</div>
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
<div class="form-check">
<label for="invalid_only" class="form-check-label">
<input id="invalid_only" name="invalid_only" type="checkbox" class="checkboxinput form-check-input" checked>
@ -53,65 +47,28 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endif %}
</div>
</div>
{# Popup to add new Soge credits manually if needed #}
<div class="modal fade" id="add-sogecredit-modal" tabindex="-1" role="dialog" aria-labelledby="addSogeCredit"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="lockNote">{% trans "Add credit from the Société générale" %}</h5>
<button type="button" class="close btn-modal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{{ form|crispy }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-modal" data-dismiss="modal">{% trans "Close" %}</button>
<button type="button" class="btn btn-success btn-modal" data-dismiss="modal" onclick="addSogeCredit()">{% trans "Add" %}</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extrajavascript %}
<script type="text/javascript">
let old_pattern = null;
let searchbar_obj = $("#searchbar");
let invalid_only_obj = $("#invalid_only");
$(document).ready(function () {
let old_pattern = null;
let searchbar_obj = $("#searchbar");
let invalid_only_obj = $("#invalid_only");
function reloadTable() {
let pattern = searchbar_obj.val();
function reloadTable() {
let pattern = searchbar_obj.val();
$("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + (
invalid_only_obj.is(':checked') ? "" : "&valid=1") + " #credits_table");
$("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + (
invalid_only_obj.is(':checked') ? "" : "&valid=1") + " #credits_table");
$(".table-row").click(function () {
window.document.location = $(this).data("href");
});
}
$(".table-row").click(function () {
window.document.location = $(this).data("href");
});
}
searchbar_obj.keyup(reloadTable);
invalid_only_obj.change(reloadTable);
function addSogeCredit() {
let user_pk = $('#id_user_pk').val()
if (!user_pk)
return
$.post('/api/treasury/soge_credit/?format=json', {
csrfmiddlewaretoken: CSRF_TOKEN,
user: user_pk,
}).done(function() {
addMsg("{% trans "Credit successfully registered" %}", 'success', 10000)
reloadTable()
}).fail(function (xhr) {
errMsg(xhr.responseJSON, 30000)
reloadTable()
})
}
searchbar_obj.keyup(reloadTable);
invalid_only_obj.change(reloadTable);
});
</script>
{% endblock %}

View File

@ -25,8 +25,7 @@ from note_kfet.settings.base import BASE_DIR
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, \
LinkTransactionToRemittanceForm, SogeCreditForm
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
@ -434,11 +433,6 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = SogeCreditForm(self.request.POST or None)
return context
class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormView, DetailView):
"""

View File

@ -43,28 +43,24 @@ class WEISurveyForm2021(forms.Form):
registration._force_save = True
registration.save()
if self.data:
self.fields["word"].choices = [(w, w) for w in WORDS]
if self.is_valid():
return
rng = Random((information.step + 1) * information.seed)
rng = Random(information.seed)
words = None
# Update seed
rng.randint(0, information.step)
buses = WEISurveyAlgorithm2021.get_buses()
informations = {bus: WEIBusInformation2021(bus) for bus in buses}
scores = sum((list(informations[bus].scores.values()) for bus in buses), [])
average_score = sum(scores) / len(scores)
preferred_words = {bus: [word for word in WORDS
if informations[bus].scores[word] >= average_score]
for bus in buses}
preferred_words = {bus: [word for word in WORDS if bus.size > 0
and WEIBusInformation2021(bus).scores[word] >= 50]
for bus in WEISurveyAlgorithm2021.get_buses()}
while words is None or len(set(words)) != len(words):
# Ensure that there is no the same word 2 times
words = [rng.choice(words) for _ignored2, words in preferred_words.items()]
rng.shuffle(words)
words = [(w, w) for w in words]
if self.data:
self.fields["word"].choices = [(w, w) for w in WORDS]
if self.is_valid():
return
self.fields["word"].choices = words
@ -170,7 +166,6 @@ class WEISurveyAlgorithm2021(WEISurveyAlgorithm):
We modify it to allow buses to have multiple "weddings".
"""
surveys = list(self.get_survey_class()(r) for r in self.get_registrations()) # All surveys
surveys = [s for s in surveys if s.is_complete()]
free_surveys = [s for s in surveys if not s.information.valid] # Remaining surveys
while free_surveys: # Some students are not affected
survey = free_surveys[0]

View File

@ -1,50 +0,0 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse
import sys
from django.core.management import BaseCommand
from django.db import transaction
from ...forms import CurrentSurvey
from ...forms.surveys.wei2021 import WORDS # WARNING: this is specific to 2021
from ...models import Bus
class Command(BaseCommand):
"""
This script is used to load scores for buses from a CSV file.
"""
def add_arguments(self, parser):
parser.add_argument('file', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help='Input CSV file')
@transaction.atomic
def handle(self, *args, **options):
file = options['file']
head = file.readline().replace('\n', '')
bus_names = head.split(';')
bus_names = [name for name in bus_names if name]
buses = []
for name in bus_names:
qs = Bus.objects.filter(name__iexact=name)
if not qs.exists():
raise ValueError(f"Bus '{name}' does not exist")
buses.append(qs.get())
informations = {bus: CurrentSurvey.get_algorithm_class().get_bus_information(bus) for bus in buses}
for line in file:
elem = line.split(';')
word = elem[0]
if word not in WORDS:
raise ValueError(f"Word {word} is not used")
for i, bus in enumerate(buses):
info = informations[bus]
info.scores[word] = float(elem[i + 1].replace(',', '.'))
for bus, info in informations.items():
info.save()
bus.save()
if options['verbosity'] > 0:
self.stdout.write(f"Bus {bus.name} saved!")

View File

@ -28,8 +28,7 @@ class Command(BaseCommand):
output = options['output']
registrations = algorithm.get_registrations()
per_bus = {bus: [r for r in registrations if 'selected_bus_pk' in r.information
and r.information['selected_bus_pk'] == bus.pk]
per_bus = {bus: [r for r in registrations if r.information['selected_bus_pk'] == bus.pk]
for bus in algorithm.get_buses()}
for bus, members in per_bus.items():
output.write(bus.name + "\n")

View File

@ -364,11 +364,8 @@ class WEIMembership(Membership):
# to treasurers.
transaction.refresh_from_db()
from treasury.models import SogeCredit
soge_credit, created = SogeCredit.objects.get_or_create(user=self.user)
soge_credit = SogeCredit.objects.get_or_create(user=self.user)[0]
soge_credit.refresh_from_db()
transaction.save()
soge_credit.transactions.add(transaction)
soge_credit.save()
soge_credit.update_transactions()
soge_credit.save()

View File

@ -490,10 +490,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView):
if "myself" in self.request.path:
user = self.request.user
else:
# To avoid unique validation issues, we use an account that can't join the WEI.
# In development mode, the note account may not exist, we use a random user (may fail)
user = User.objects.get(username="note") \
if User.objects.filter(username="note").exists() else User.objects.first()
user = User.objects.get(username="note")
return WEIRegistration(
wei=wei,
user=user,
@ -565,10 +562,7 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView):
if "myself" in self.request.path:
user = self.request.user
else:
# To avoid unique validation issues, we use an account that can't join the WEI.
# In development mode, the note account may not exist, we use a random user (may fail)
user = User.objects.get(username="note") \
if User.objects.filter(username="note").exists() else User.objects.first()
user = User.objects.get(username="note")
return WEIRegistration(
wei=wei,
user=user,
@ -704,8 +698,7 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields["user"].disabled = True
# The auto-json-format may cause issues with the default field remove
if not PermissionBackend.check_perm(self.request, 'wei.change_weiregistration_information_json', self.object):
if not self.object.first_year:
del form.fields["information_json"]
return form

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-06 00:45+0200\n"
"POT-Creation-Date: 2021-06-15 21:17+0200\n"
"PO-Revision-Date: 2020-11-16 20:02+0000\n"
"Last-Translator: Yohann D'ANELLO <ynerant@crans.org>\n"
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
@ -111,7 +111,7 @@ msgid "type"
msgstr "type"
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:305
#: apps/note/models/notes.py:148 apps/treasury/models.py:286
#: apps/note/models/notes.py:148 apps/treasury/models.py:283
#: apps/wei/models.py:165 apps/wei/templates/wei/survey.html:15
msgid "user"
msgstr "utilisateur"
@ -251,19 +251,19 @@ msgstr "Entré le "
msgid "remove"
msgstr "supprimer"
#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:200
#: apps/activity/tables.py:80 apps/note/forms.py:68 apps/treasury/models.py:197
msgid "Type"
msgstr "Type"
#: apps/activity/tables.py:82 apps/member/forms.py:186
#: apps/registration/forms.py:90 apps/treasury/forms.py:131
#: apps/registration/forms.py:90 apps/treasury/forms.py:130
#: apps/wei/forms/registration.py:96
msgid "Last name"
msgstr "Nom de famille"
#: apps/activity/tables.py:84 apps/member/forms.py:191
#: apps/note/templates/note/transaction_form.html:134
#: apps/registration/forms.py:95 apps/treasury/forms.py:133
#: apps/registration/forms.py:95 apps/treasury/forms.py:132
#: apps/wei/forms/registration.py:101
msgid "First name"
msgstr "Prénom"
@ -327,7 +327,7 @@ msgstr "Entrée effectuée !"
#: apps/member/templates/member/add_members.html:46
#: apps/member/templates/member/club_form.html:16
#: apps/note/templates/note/transactiontemplate_form.html:18
#: apps/treasury/forms.py:89 apps/treasury/forms.py:143
#: apps/treasury/forms.py:88 apps/treasury/forms.py:142
#: apps/treasury/templates/treasury/invoice_form.html:74
#: apps/wei/templates/wei/bus_form.html:17
#: apps/wei/templates/wei/busteam_form.html:17
@ -540,8 +540,8 @@ msgstr "Taille maximale : 2 Mo"
msgid "This image cannot be loaded."
msgstr "Cette image ne peut pas être chargée."
#: apps/member/forms.py:141 apps/member/views.py:102
#: apps/registration/forms.py:33 apps/registration/views.py:259
#: apps/member/forms.py:141 apps/member/views.py:100
#: apps/registration/forms.py:33 apps/registration/views.py:254
msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà."
@ -573,7 +573,7 @@ msgid "Credit amount"
msgstr "Montant à créditer"
#: apps/member/forms.py:196 apps/note/templates/note/transaction_form.html:140
#: apps/registration/forms.py:100 apps/treasury/forms.py:135
#: apps/registration/forms.py:100 apps/treasury/forms.py:134
#: apps/wei/forms/registration.py:106
msgid "Bank"
msgstr "Banque"
@ -835,7 +835,7 @@ msgstr "Le rôle {role} ne s'applique pas au club {club}."
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
#: apps/member/models.py:443 apps/member/views.py:660
#: apps/member/models.py:443 apps/member/views.py:661
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
@ -944,8 +944,7 @@ msgstr ""
"déverrouiller lui-même."
#: apps/member/templates/member/base.html:110
#: apps/member/templates/member/base.html:137 apps/treasury/forms.py:91
#: apps/treasury/templates/treasury/sogecredit_list.html:72
#: apps/member/templates/member/base.html:137 apps/treasury/forms.py:90
msgid "Close"
msgstr "Fermer"
@ -969,8 +968,6 @@ msgstr "Alias de la note"
#: apps/member/templates/member/club_alias.html:20
#: apps/member/templates/member/profile_alias.html:19
#: apps/treasury/tables.py:99
#: apps/treasury/templates/treasury/sogecredit_list.html:34
#: apps/treasury/templates/treasury/sogecredit_list.html:73
msgid "Add"
msgstr "Ajouter"
@ -1136,7 +1133,7 @@ msgstr "Inscriptions"
msgid "This address must be valid."
msgstr "Cette adresse doit être valide."
#: apps/member/views.py:139
#: apps/member/views.py:138
msgid "Profile detail"
msgstr "Détails de l'utilisateur"
@ -1172,7 +1169,7 @@ msgstr "Modifier le club"
msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club"
#: apps/member/views.py:642 apps/wei/views.py:932
#: apps/member/views.py:642 apps/wei/views.py:917
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@ -1180,19 +1177,19 @@ 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:664
#: apps/member/views.py:665
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:669
#: apps/member/views.py:670
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:815
#: apps/member/views.py:816
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:840
#: apps/member/views.py:841
msgid "Members of the club"
msgstr "Membres du club"
@ -1478,8 +1475,8 @@ msgstr ""
"mode de paiement et un utilisateur ou un club"
#: apps/note/models/transactions.py:355 apps/note/models/transactions.py:358
#: apps/note/models/transactions.py:361 apps/wei/views.py:937
#: apps/wei/views.py:941
#: apps/note/models/transactions.py:361 apps/wei/views.py:922
#: apps/wei/views.py:926
msgid "This field is required."
msgstr "Ce champ est requis."
@ -1495,7 +1492,7 @@ msgstr "Transactions de crédit/retrait"
msgid "membership transaction"
msgstr "transaction d'adhésion"
#: apps/note/models/transactions.py:385 apps/treasury/models.py:293
#: apps/note/models/transactions.py:385 apps/treasury/models.py:289
msgid "membership transactions"
msgstr "transactions d'adhésion"
@ -1602,14 +1599,14 @@ msgid "Action"
msgstr "Action"
#: apps/note/templates/note/transaction_form.html:112
#: apps/treasury/forms.py:137 apps/treasury/tables.py:67
#: apps/treasury/forms.py:136 apps/treasury/tables.py:67
#: apps/treasury/tables.py:132
#: apps/treasury/templates/treasury/remittance_form.html:23
msgid "Amount"
msgstr "Montant"
#: apps/note/templates/note/transaction_form.html:128
#: apps/treasury/models.py:55
#: apps/treasury/models.py:52
msgid "Name"
msgstr "Nom"
@ -2067,18 +2064,18 @@ msgstr "Utilisateurs en attente d'inscription"
msgid "Registration detail"
msgstr "Détails de l'inscription"
#: apps/registration/views.py:279
#: apps/registration/views.py:278
msgid "You must join the BDE."
msgstr "Vous devez adhérer au BDE."
#: apps/registration/views.py:303
#: apps/registration/views.py:302
msgid ""
"The entered amount is not enough for the memberships, should be at least {}"
msgstr ""
"Le montant crédité est trop faible pour adhérer, il doit être au minimum de "
"{}"
#: apps/registration/views.py:384
#: apps/registration/views.py:383
msgid "Invalidate pre-registration"
msgstr "Invalider l'inscription"
@ -2086,145 +2083,145 @@ msgstr "Invalider l'inscription"
msgid "Treasury"
msgstr "Trésorerie"
#: apps/treasury/forms.py:26 apps/treasury/models.py:94
#: apps/treasury/forms.py:25 apps/treasury/models.py:91
#: apps/treasury/templates/treasury/invoice_form.html:22
msgid "This invoice is locked and can no longer be edited."
msgstr "Cette facture est verrouillée et ne peut plus être éditée."
#: apps/treasury/forms.py:100
#: apps/treasury/forms.py:99
msgid "Remittance is already closed."
msgstr "La remise est déjà fermée."
#: apps/treasury/forms.py:105
#: apps/treasury/forms.py:104
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:125 apps/treasury/models.py:268
#: apps/treasury/forms.py:124 apps/treasury/models.py:265
#: 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
#: apps/treasury/templates/treasury/sogecredit_list.html:17
#: apps/treasury/templates/treasury/sogecredit_list.html:16
msgid "Remittance"
msgstr "Remise"
#: apps/treasury/forms.py:126
#: apps/treasury/forms.py:125
msgid "No attached remittance"
msgstr "Pas de remise associée"
#: apps/treasury/models.py:27
#: apps/treasury/models.py:24
msgid "Invoice identifier"
msgstr "Numéro de facture"
#: apps/treasury/models.py:41
#: apps/treasury/models.py:38
msgid "BDE"
msgstr "BDE"
#: apps/treasury/models.py:46
#: apps/treasury/models.py:43
msgid "Object"
msgstr "Objet"
#: apps/treasury/models.py:50
#: apps/treasury/models.py:47
msgid "Description"
msgstr "Description"
#: apps/treasury/models.py:59
#: apps/treasury/models.py:56
msgid "Address"
msgstr "Adresse"
#: apps/treasury/models.py:64 apps/treasury/models.py:194
#: apps/treasury/models.py:61 apps/treasury/models.py:191
msgid "Date"
msgstr "Date"
#: apps/treasury/models.py:68
#: apps/treasury/models.py:65
msgid "Acquitted"
msgstr "Acquittée"
#: apps/treasury/models.py:73
#: apps/treasury/models.py:70
msgid "Locked"
msgstr "Verrouillée"
#: apps/treasury/models.py:74
#: apps/treasury/models.py:71
msgid "An invoice can't be edited when it is locked."
msgstr "Une facture ne peut plus être modifiée si elle est verrouillée."
#: apps/treasury/models.py:80
#: apps/treasury/models.py:77
msgid "tex source"
msgstr "fichier TeX source"
#: apps/treasury/models.py:114 apps/treasury/models.py:130
#: apps/treasury/models.py:111 apps/treasury/models.py:127
msgid "invoice"
msgstr "facture"
#: apps/treasury/models.py:115
#: apps/treasury/models.py:112
msgid "invoices"
msgstr "factures"
#: apps/treasury/models.py:118
#: apps/treasury/models.py:115
#, python-brace-format
msgid "Invoice #{id}"
msgstr "Facture n°{id}"
#: apps/treasury/models.py:135
#: apps/treasury/models.py:132
msgid "Designation"
msgstr "Désignation"
#: apps/treasury/models.py:141
#: apps/treasury/models.py:138
msgid "Quantity"
msgstr "Quantité"
#: apps/treasury/models.py:146
#: apps/treasury/models.py:143
msgid "Unit price"
msgstr "Prix unitaire"
#: apps/treasury/models.py:162
#: apps/treasury/models.py:159
msgid "product"
msgstr "produit"
#: apps/treasury/models.py:163
#: apps/treasury/models.py:160
msgid "products"
msgstr "produits"
#: apps/treasury/models.py:183
#: apps/treasury/models.py:180
msgid "remittance type"
msgstr "type de remise"
#: apps/treasury/models.py:184
#: apps/treasury/models.py:181
msgid "remittance types"
msgstr "types de remises"
#: apps/treasury/models.py:205
#: apps/treasury/models.py:202
msgid "Comment"
msgstr "Commentaire"
#: apps/treasury/models.py:210
#: apps/treasury/models.py:207
msgid "Closed"
msgstr "Fermée"
#: apps/treasury/models.py:214
#: apps/treasury/models.py:211
msgid "remittance"
msgstr "remise"
#: apps/treasury/models.py:215
#: apps/treasury/models.py:212
msgid "remittances"
msgstr "remises"
#: apps/treasury/models.py:248
#: apps/treasury/models.py:245
msgid "Remittance #{:d}: {}"
msgstr "Remise n°{:d} : {}"
#: apps/treasury/models.py:272
#: apps/treasury/models.py:269
msgid "special transaction proxy"
msgstr "proxy de transaction spéciale"
#: apps/treasury/models.py:273
#: apps/treasury/models.py:270
msgid "special transaction proxies"
msgstr "proxys de transactions spéciales"
#: apps/treasury/models.py:299
#: apps/treasury/models.py:295
msgid "credit transaction"
msgstr "transaction de crédit"
#: apps/treasury/models.py:418
#: apps/treasury/models.py:379
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."
@ -2232,16 +2229,16 @@ 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:438
#: apps/treasury/models.py:399
#: 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:439
#: apps/treasury/models.py:400
msgid "Credits from the Société générale"
msgstr "Crédits de la Société générale"
#: apps/treasury/models.py:442
#: apps/treasury/models.py:403
#, python-brace-format
msgid "Soge credit for {user}"
msgstr "Crédit de la société générale pour l'utilisateur {user}"
@ -2253,7 +2250,7 @@ msgstr "Facture n°{:d}"
#: apps/treasury/tables.py:25
#: apps/treasury/templates/treasury/invoice_list.html:13
#: apps/treasury/templates/treasury/remittance_list.html:13
#: apps/treasury/templates/treasury/sogecredit_list.html:14
#: apps/treasury/templates/treasury/sogecredit_list.html:13
msgid "Invoice"
msgstr "Facture"
@ -2270,12 +2267,12 @@ msgid "Yes"
msgstr "Oui"
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:10
#: apps/treasury/views.py:180
#: apps/treasury/views.py:179
msgid "Delete invoice"
msgstr "Supprimer la facture"
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:15
#: apps/treasury/views.py:184
#: apps/treasury/views.py:183
msgid "This invoice is locked and can't be deleted."
msgstr "Cette facture est verrouillée et ne peut pas être supprimée."
@ -2309,7 +2306,7 @@ msgstr "Retirer produit"
#: apps/treasury/templates/treasury/invoice_list.html:19
#: apps/treasury/templates/treasury/remittance_list.html:19
#: apps/treasury/templates/treasury/sogecredit_list.html:20
#: apps/treasury/templates/treasury/sogecredit_list.html:19
msgid "Société générale credits"
msgstr "Crédits de la Société générale"
@ -2429,62 +2426,54 @@ msgstr "Valider"
msgid "Return to credit list"
msgstr "Retour à la liste des crédits"
#: apps/treasury/templates/treasury/sogecredit_list.html:40
#: apps/treasury/templates/treasury/sogecredit_list.html:34
msgid "Filter with unvalidated credits only"
msgstr "Filtrer avec uniquement les crédits non valides"
#: apps/treasury/templates/treasury/sogecredit_list.html:50
#: apps/treasury/templates/treasury/sogecredit_list.html:44
msgid "There is no matched user that have asked for a Société générale credit."
msgstr ""
"Il n'y a pas d'utilisateur trouvé ayant demandé un crédit de la Société "
"générale."
#: apps/treasury/templates/treasury/sogecredit_list.html:63
msgid "Add credit from the Société générale"
msgstr "Ajouter un crédit de la Société générale"
#: apps/treasury/templates/treasury/sogecredit_list.html:109
msgid "Credit successfully registered"
msgstr "Le crédit a bien été enregistré"
#: apps/treasury/views.py:40
#: apps/treasury/views.py:39
msgid "Create new invoice"
msgstr "Créer une nouvelle facture"
#: apps/treasury/views.py:97
#: apps/treasury/views.py:96
msgid "Invoices list"
msgstr "Liste des factures"
#: apps/treasury/views.py:112 apps/treasury/views.py:286
#: apps/treasury/views.py:412
#: apps/treasury/views.py:111 apps/treasury/views.py:285
#: apps/treasury/views.py:411
msgid "You are not able to see the treasury interface."
msgstr "Vous n'êtes pas autorisé à voir l'interface de trésorerie."
#: apps/treasury/views.py:122
#: apps/treasury/views.py:121
msgid "Update an invoice"
msgstr "Modifier la facture"
#: apps/treasury/views.py:247
#: apps/treasury/views.py:246
msgid "Create a new remittance"
msgstr "Créer une nouvelle remise"
#: apps/treasury/views.py:274
#: apps/treasury/views.py:273
msgid "Remittances list"
msgstr "Liste des remises"
#: apps/treasury/views.py:337
#: apps/treasury/views.py:336
msgid "Update a remittance"
msgstr "Modifier la remise"
#: apps/treasury/views.py:360
#: apps/treasury/views.py:359
msgid "Attach a transaction to a remittance"
msgstr "Joindre une transaction à une remise"
#: apps/treasury/views.py:404
#: apps/treasury/views.py:403
msgid "List of credits from the Société générale"
msgstr "Liste des crédits de la Société générale"
#: apps/treasury/views.py:449
#: apps/treasury/views.py:443
msgid "Manage credits from the Société générale"
msgstr "Gérer les crédits de la Société générale"
@ -2724,11 +2713,11 @@ msgstr "Prix du WEI (étudiants)"
msgid "WEI list"
msgstr "Liste des WEI"
#: apps/wei/templates/wei/base.html:81 apps/wei/views.py:517
#: apps/wei/templates/wei/base.html:81 apps/wei/views.py:510
msgid "Register 1A"
msgstr "Inscrire un 1A"
#: apps/wei/templates/wei/base.html:85 apps/wei/views.py:592
#: apps/wei/templates/wei/base.html:85 apps/wei/views.py:578
msgid "Register 2A+"
msgstr "Inscrire un 2A+"
@ -2757,8 +2746,8 @@ msgstr "Télécharger au format PDF"
#: apps/wei/templates/wei/survey.html:11
#: apps/wei/templates/wei/survey_closed.html:11
#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:988
#: apps/wei/views.py:1043 apps/wei/views.py:1053
#: apps/wei/templates/wei/survey_end.html:11 apps/wei/views.py:973
#: apps/wei/views.py:1028 apps/wei/views.py:1038
msgid "Survey WEI"
msgstr "Questionnaire WEI"
@ -2996,11 +2985,11 @@ msgstr "Gérer l'équipe WEI"
msgid "Register first year student to the WEI"
msgstr "Inscrire un 1A au WEI"
#: apps/wei/views.py:539 apps/wei/views.py:627
#: apps/wei/views.py:532 apps/wei/views.py:613
msgid "This user is already registered to this WEI."
msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:544
#: apps/wei/views.py:537
msgid ""
"This user can't be in her/his first year since he/she has already "
"participated to a WEI."
@ -3008,27 +2997,27 @@ msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'il a déjà "
"participé à un WEI."
#: apps/wei/views.py:561
#: apps/wei/views.py:554
msgid "Register old student to the WEI"
msgstr "Inscrire un 2A+ au WEI"
#: apps/wei/views.py:611 apps/wei/views.py:700
#: apps/wei/views.py:597 apps/wei/views.py:686
msgid "You already opened an account in the Société générale."
msgstr "Vous avez déjà ouvert un compte auprès de la société générale."
#: apps/wei/views.py:657
#: apps/wei/views.py:643
msgid "Update WEI Registration"
msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:761
#: apps/wei/views.py:746
msgid "Delete WEI registration"
msgstr "Supprimer l'inscription WEI"
#: apps/wei/views.py:772
#: apps/wei/views.py:757
msgid "You don't have the right to delete this WEI registration."
msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI."
#: apps/wei/views.py:791
#: apps/wei/views.py:776
msgid "Validate WEI registration"
msgstr "Valider l'inscription WEI"
@ -3152,7 +3141,13 @@ msgstr ""
"Vous n'êtes plus adhérent BDE. Merci de réadhérer si vous voulez profiter de "
"la note."
#: note_kfet/templates/base.html:166
#: note_kfet/templates/base.html:164
msgid "You are not a Kfet member, so you can't use your note account."
msgstr ""
"Vous n'êtes pas adhérent Kfet, vous ne pouvez par conséquent pas utiliser "
"votre compte note."
#: note_kfet/templates/base.html:170
msgid ""
"Your e-mail address is not validated. Please check your mail inbox and click "
"on the validation link."
@ -3160,7 +3155,7 @@ 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
#: note_kfet/templates/base.html:176
msgid ""
"You declared that you opened a bank account in the Société générale. The "
"bank did not validate the creation of the account to the BDE, so the "
@ -3175,7 +3170,7 @@ msgstr ""
"durer quelques jours. Merci de vous assurer de bien aller au bout de vos "
"démarches."
#: note_kfet/templates/base.html:195
#: note_kfet/templates/base.html:199
msgid "Contact us"
msgstr "Nous contacter"
@ -3223,10 +3218,9 @@ msgid ""
"link templates and convert permissions to scope numbers with the permissions "
"that you want to grant for your application."
msgstr ""
"Vous pouvez aller <a href=\"%(scopes_url)s\">ici</a> pour générer des "
"modèles de liens d'autorisation et convertir des permissions en identifiants "
"de scopes avec les permissions que vous souhaitez attribuer à votre "
"application."
"Vous pouvez aller <a href=\"%(scopes_url)s\">ici</a> pour générer des modèles "
"de liens d'autorisation et convertir des permissions en identifiants de "
"scopes avec les permissions que vous souhaitez attribuer à votre application."
#: note_kfet/templates/oauth2_provider/application_detail.html:37
#: note_kfet/templates/oauth2_provider/application_form.html:23
@ -3406,8 +3400,3 @@ msgstr ""
"vous connecter. Vous devez vous rendre à la Kfet et payer les frais "
"d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu."
#~ msgid "You are not a Kfet member, so you can't use your note account."
#~ msgstr ""
#~ "Vous n'êtes pas adhérent Kfet, vous ne pouvez par conséquent pas utiliser "
#~ "votre compte note."