diff --git a/apps/member/forms.py b/apps/member/forms.py index 89ce3993..b34a3260 100644 --- a/apps/member/forms.py +++ b/apps/member/forms.py @@ -28,7 +28,7 @@ class ProfileForm(forms.ModelForm): class Meta: model = Profile fields = '__all__' - exclude = ('user', 'email_confirmed', 'registration_valid', 'soge', ) + exclude = ('user', 'email_confirmed', 'registration_valid', ) class ClubForm(forms.ModelForm): diff --git a/apps/member/models.py b/apps/member/models.py index 35406d54..4be1b1a4 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -64,11 +64,12 @@ class Profile(models.Model): default=False, ) - soge = models.BooleanField( - verbose_name=_("Société générale"), - help_text=_("Has the user ever be paid by the Société générale?"), - default=False, - ) + @property + def soge(self): + if "treasury" in settings.INSTALLED_APPS: + from treasury.models import SogeCredit + return SogeCredit.objects.filter(user=self.user, credit_transaction=None).exists() + return False class Meta: verbose_name = _('user profile') @@ -309,7 +310,20 @@ class Membership(models.Model): reason="Adhésion " + self.club.name, ) transaction._force_save = True - transaction.save(force_insert=True) + print(hasattr(self, '_soge')) + if hasattr(self, '_soge') and "treasury" in settings.INSTALLED_APPS: + # If the soge pays, then the transaction is unvalidated in a first time, then submitted for control + # to treasurers. + transaction.valid = False + from treasury.models import SogeCredit + soge_credit = SogeCredit.objects.get_or_create(user=self.user)[0] + soge_credit.refresh_from_db() + transaction.save(force_insert=True) + transaction.refresh_from_db() + soge_credit.transactions.add(transaction) + soge_credit.save() + else: + transaction.save(force_insert=True) def __str__(self): return _("Membership of {user} for the club {club}").format(user=self.user.username, club=self.club.name, ) diff --git a/apps/member/views.py b/apps/member/views.py index 879b103c..4a9f1995 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -18,7 +18,7 @@ from django.views.generic.edit import FormMixin from django_tables2.views import SingleTableView from rest_framework.authtoken.models import Token from note.forms import ImageForm -from note.models import Alias, NoteUser, NoteSpecial +from note.models import Alias, NoteUser from note.models.transactions import Transaction, SpecialTransaction from note.tables import HistoryTable, AliasTable from permission.backends import PermissionBackend @@ -128,7 +128,8 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): context = super().get_context_data(**kwargs) user = context['user_object'] history_list = \ - Transaction.objects.all().filter(Q(source=user.note) | Q(destination=user.note)).order_by("-id")\ + Transaction.objects.all().filter(Q(source=user.note) | Q(destination=user.note))\ + .order_by("-created_at", "-id")\ .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")) history_table = HistoryTable(history_list, prefix='transaction-') history_table.paginate(per_page=20, page=self.request.GET.get("transaction-page", 1)) @@ -314,7 +315,8 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): club.update_membership_dates() club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\ - .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by('-id') + .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\ + .order_by('-created_at', '-id') history_table = HistoryTable(club_transactions, prefix="history-") history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1)) context['history_list'] = history_table @@ -365,6 +367,15 @@ class ClubUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): form_class = ClubForm template_name = "member/club_form.html" + def get_queryset(self, **kwargs): + qs = super().get_queryset(**kwargs) + + # Don't update a WEI club through this view + if "wei" in settings.INSTALLED_APPS: + qs = qs.filter(weiclub=None) + + return qs + def get_success_url(self): return reverse_lazy("member:club_detail", kwargs={"pk": self.object.pk}) @@ -396,7 +407,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): if "club_pk" in self.kwargs: # We create a new membership. club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\ - .get(pk=self.kwargs["club_pk"]) + .get(pk=self.kwargs["club_pk"], weiclub=None) form.fields['credit_amount'].initial = club.membership_fee_paid form.fields['roles'].initial = Role.objects.filter(name="Membre de club").all() @@ -463,17 +474,11 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): bank = form.cleaned_data["bank"] soge = form.cleaned_data["soge"] and not user.profile.soge and club.name == "BDE" - # If Société générale pays, then we auto-fill some data + # If Société générale pays, then we store that information but the payment must be controlled by treasurers + # later. The membership transaction will be invalidated. if soge: - credit_type = NoteSpecial.objects.get(special_type="Virement bancaire") - bde = club - kfet = Club.objects.get(name="Kfet") - if user.profile.paid: - fee = bde.membership_fee_paid + kfet.membership_fee_paid - else: - fee = bde.membership_fee_unpaid + kfet.membership_fee_unpaid - credit_amount = fee - bank = "Société générale" + credit_type = None + form.instance._soge = True if credit_type is None: credit_amount = 0 @@ -546,11 +551,9 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): ret = super().form_valid(form) - # If Société générale pays, then we store the information: the bank can't pay twice to a same person. + # If Société générale pays, then we assume that this is the BDE membership, and we auto-renew the + # Kfet membership. if soge: - user.profile.soge = True - user.profile.save() - kfet = Club.objects.get(name="Kfet") kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid @@ -562,13 +565,16 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): date_end__gte=datetime.today(), ) - membership = Membership.objects.create( + membership = Membership( club=kfet, user=user, fee=kfet_fee, date_start=old_membership.get().date_end + timedelta(days=1) if old_membership.exists() else form.instance.date_start, ) + membership._soge = True + membership.save() + membership.refresh_from_db() if old_membership.exists(): membership.roles.set(old_membership.get().roles.all()) else: diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py index 83f8f914..081f6022 100644 --- a/apps/note/models/transactions.py +++ b/apps/note/models/transactions.py @@ -8,6 +8,7 @@ from django.utils.translation import gettext_lazy as _ from polymorphic.models import PolymorphicModel from .notes import Note, NoteClub, NoteSpecial +from ..templatetags.pretty_money import pretty_money """ Defines transactions @@ -198,6 +199,14 @@ class Transaction(PolymorphicModel): self.source.save() 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 @@ -206,6 +215,10 @@ class Transaction(PolymorphicModel): def type(self): return _('Transfer') + def __str__(self): + return self.__class__.__name__ + " from " + str(self.source) + " to " + str(self.destination) + " of "\ + + pretty_money(self.quantity * self.amount) + ("" if self.valid else " invalid") + class RecurrentTransaction(Transaction): """ diff --git a/apps/note/signals.py b/apps/note/signals.py index 115ddab9..0baa39e6 100644 --- a/apps/note/signals.py +++ b/apps/note/signals.py @@ -10,7 +10,7 @@ def save_user_note(instance, raw, **_kwargs): # When provisionning data, do not try to autocreate return - if (instance.is_superuser or instance.profile.registration_valid) and instance.is_active: + if instance.is_superuser or instance.profile.registration_valid: # Create note only when the registration is validated from note.models import NoteUser NoteUser.objects.get_or_create(user=instance) diff --git a/apps/note/views.py b/apps/note/views.py index 88d47847..b26e6cf1 100644 --- a/apps/note/views.py +++ b/apps/note/views.py @@ -30,7 +30,7 @@ class TransactionCreateView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTabl table_class = HistoryTable def get_queryset(self, **kwargs): - return super().get_queryset(**kwargs).order_by("-id").all()[:20] + return super().get_queryset(**kwargs).order_by("-created_at", "-id").all()[:20] def get_context_data(self, **kwargs): """ @@ -93,7 +93,7 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): table_class = HistoryTable def get_queryset(self, **kwargs): - return super().get_queryset(**kwargs).order_by("-id").all()[:20] + return super().get_queryset(**kwargs).order_by("-created_at", "-id").all()[:20] def get_context_data(self, **kwargs): """ diff --git a/apps/registration/views.py b/apps/registration/views.py index 0e5977d7..86fb9d82 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -16,13 +16,12 @@ from django.views.generic.edit import FormMixin from django_tables2 import SingleTableView from member.forms import ProfileForm from member.models import Membership, Club, Role -from note.models import SpecialTransaction, NoteSpecial +from note.models import SpecialTransaction from note.templatetags.pretty_money import pretty_money from permission.backends import PermissionBackend from permission.views import ProtectQuerysetMixin -from wei.models import WEIClub -from .forms import SignUpForm, ValidationForm, WEISignupForm +from .forms import SignUpForm, ValidationForm from .tables import FutureUserTable from .tokens import email_validation_token @@ -40,16 +39,6 @@ class UserCreateView(CreateView): context = super().get_context_data(**kwargs) context["profile_form"] = self.second_form() - if "wei" in settings.INSTALLED_APPS: - from wei.forms import WEIRegistrationForm - wei_form = WEIRegistrationForm() - del wei_form.fields["user"] - del wei_form.fields["caution_check"] - del wei_form.fields["first_year"] - del wei_form.fields["information_json"] - context["wei_form"] = wei_form - context["wei_registration_form"] = WEISignupForm() - return context def form_valid(self, form): @@ -62,23 +51,6 @@ class UserCreateView(CreateView): if not profile_form.is_valid(): return self.form_invalid(form) - wei_form = None - self.wei = False - - if "wei" in settings.INSTALLED_APPS: - wei_signup_form = WEISignupForm(self.request.POST) - if wei_signup_form.is_valid() and wei_signup_form.cleaned_data["wei_registration"]: - from wei.forms import WEIRegistrationForm - wei_form = WEIRegistrationForm(self.request.POST) - del wei_form.fields["user"] - del wei_form.fields["caution_check"] - del wei_form.fields["first_year"] - - if not wei_form.is_valid(): - return self.form_invalid(wei_form) - - self.wei = True - # Save the user and the profile user = form.save(commit=False) user.is_active = False @@ -92,21 +64,10 @@ class UserCreateView(CreateView): user.profile.send_email_validation_link() - if self.wei: - wei_registration = wei_form.instance - wei_registration.user = user - wei_registration.wei = WEIClub.objects.order_by('date_start').last() - wei_registration.caution_check = False - wei_registration.first_year = True - wei_registration.save() - return super().form_valid(form) def get_success_url(self): - if self.wei: - return reverse_lazy('registration:email_validation_sent') # TODO Load WEI survey - else: - return reverse_lazy('registration:email_validation_sent') + return reverse_lazy('registration:email_validation_sent') class UserValidateView(TemplateView): @@ -304,17 +265,17 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, fee += kfet_fee if soge: - # Fill payment information if Société Générale pays the inscription - credit_type = NoteSpecial.objects.get(special_type="Virement bancaire") - credit_amount = fee - bank = "Société générale" + # If the bank pays, then we don't credit now. Treasurers will validate the transaction + # and credit the note later. + credit_type = None - print("OK") + if credit_type is None: + credit_amount = 0 if join_Kfet and not join_BDE: form.add_error('join_Kfet', _("You must join BDE club before joining Kfet club.")) - if fee > credit_amount: + if fee > credit_amount and not soge: # Check if the user credits enough money form.add_error('credit_type', _("The entered amount is not enough for the memberships, should be at least {}") @@ -336,10 +297,9 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, ret = super().form_valid(form) user.is_active = user.profile.email_confirmed or user.is_superuser user.profile.registration_valid = True - # Store if Société générale paid for next years - user.profile.soge = soge user.save() user.profile.save() + user.refresh_from_db() if credit_type is not None and credit_amount > 0: # Credit the note @@ -357,21 +317,29 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, if join_BDE: # Create membership for the user to the BDE starting today - membership = Membership.objects.create( + membership = Membership( club=bde, user=user, fee=bde_fee, ) + if soge: + membership._soge = True + membership.save() + membership.refresh_from_db() membership.roles.add(Role.objects.get(name="Adhérent BDE")) membership.save() if join_Kfet: # Create membership for the user to the Kfet starting today - membership = Membership.objects.create( + membership = Membership( club=kfet, user=user, fee=kfet_fee, ) + if soge: + membership._soge = True + membership.save() + membership.refresh_from_db() membership.roles.add(Role.objects.get(name="Adhérent Kfet")) membership.save() diff --git a/apps/treasury/admin.py b/apps/treasury/admin.py index abeec3e3..9c8aaf2e 100644 --- a/apps/treasury/admin.py +++ b/apps/treasury/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin -from .models import RemittanceType, Remittance +from .models import RemittanceType, Remittance, SogeCredit @admin.register(RemittanceType) @@ -25,3 +25,6 @@ class RemittanceAdmin(admin.ModelAdmin): if not obj: return True return not obj.closed and super().has_change_permission(request, obj) + + +admin.site.register(SogeCredit) diff --git a/apps/treasury/api/serializers.py b/apps/treasury/api/serializers.py index f1bbef75..0acb0aa1 100644 --- a/apps/treasury/api/serializers.py +++ b/apps/treasury/api/serializers.py @@ -4,7 +4,7 @@ from rest_framework import serializers from note.api.serializers import SpecialTransactionSerializer -from ..models import Invoice, Product, RemittanceType, Remittance +from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit class ProductSerializer(serializers.ModelSerializer): @@ -60,3 +60,14 @@ class RemittanceSerializer(serializers.ModelSerializer): def get_transactions(self, obj): return serializers.ListSerializer(child=SpecialTransactionSerializer()).to_representation(obj.transactions) + + +class SogeCreditSerializer(serializers.ModelSerializer): + """ + REST API Serializer for SogeCredit types. + The djangorestframework plugin will analyse the model `SogeCredit` and parse all fields in the API. + """ + + class Meta: + model = SogeCredit + fields = '__all__' diff --git a/apps/treasury/api/urls.py b/apps/treasury/api/urls.py index 30ac00e1..70d81f77 100644 --- a/apps/treasury/api/urls.py +++ b/apps/treasury/api/urls.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet +from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet, SogeCreditViewSet def register_treasury_urls(router, path): @@ -12,3 +12,4 @@ def register_treasury_urls(router, path): router.register(path + '/product', ProductViewSet) router.register(path + '/remittance_type', RemittanceTypeViewSet) router.register(path + '/remittance', RemittanceViewSet) + router.register(path + '/soge_credit', SogeCreditViewSet) diff --git a/apps/treasury/api/views.py b/apps/treasury/api/views.py index 7a70fd24..ee97e6ac 100644 --- a/apps/treasury/api/views.py +++ b/apps/treasury/api/views.py @@ -5,8 +5,9 @@ from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import SearchFilter from api.viewsets import ReadProtectedModelViewSet -from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer -from ..models import Invoice, Product, RemittanceType, Remittance +from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer,\ + SogeCreditSerializer +from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit class InvoiceViewSet(ReadProtectedModelViewSet): @@ -39,7 +40,7 @@ class RemittanceTypeViewSet(ReadProtectedModelViewSet): The djangorestframework plugin will get all `RemittanceType` objects, serialize it to JSON with the given serializer then render it on /api/treasury/remittance_type/ """ - queryset = RemittanceType.objects.all() + queryset = RemittanceType.objects serializer_class = RemittanceTypeSerializer @@ -49,5 +50,15 @@ class RemittanceViewSet(ReadProtectedModelViewSet): The djangorestframework plugin will get all `Remittance` objects, serialize it to JSON with the given serializer, then render it on /api/treasury/remittance/ """ - queryset = Remittance.objects.all() + queryset = Remittance.objects serializer_class = RemittanceSerializer + + +class SogeCreditViewSet(ReadProtectedModelViewSet): + """ + REST API View set. + The djangorestframework plugin will get all `SogeCredit` objects, serialize it to JSON with the given serializer, + then render it on /api/treasury/soge_credit/ + """ + queryset = SogeCredit.objects + serializer_class = SogeCreditSerializer diff --git a/apps/treasury/models.py b/apps/treasury/models.py index ca1da3a4..42a8c8cf 100644 --- a/apps/treasury/models.py +++ b/apps/treasury/models.py @@ -1,11 +1,13 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +from datetime import datetime +from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db import models from django.db.models import Q from django.utils.translation import gettext_lazy as _ -from note.models import NoteSpecial, SpecialTransaction +from note.models import NoteSpecial, SpecialTransaction, MembershipTransaction class Invoice(models.Model): @@ -207,3 +209,90 @@ class SpecialTransactionProxy(models.Model): class Meta: verbose_name = _("special transaction proxy") verbose_name_plural = _("special transaction proxies") + + +class SogeCredit(models.Model): + """ + Manage the credits from the Société générale. + """ + user = models.OneToOneField( + User, + on_delete=models.PROTECT, + verbose_name=_("user"), + ) + + transactions = models.ManyToManyField( + MembershipTransaction, + related_name="+", + verbose_name=_("membership transactions"), + ) + + credit_transaction = models.OneToOneField( + SpecialTransaction, + on_delete=models.SET_NULL, + verbose_name=_("credit transaction"), + null=True, + ) + + @property + def valid(self): + return self.credit_transaction is not None + + @property + def amount(self): + return sum(transaction.quantity * transaction.amount for transaction in self.transactions.all()) + + def invalidate(self): + """ + Invalidating a Société générale delete the transaction of the bank if it was already created. + Treasurers must know what they do, With Great Power Comes Great Responsibility... + """ + if self.valid: + self.credit_transaction.valid = False + self.credit_transaction.save() + self.credit_transaction.delete() + self.credit_transaction = None + for transaction in self.transactions.all(): + transaction.valid = False + transaction.save() + + def validate(self, force=False): + if self.valid and not force: + # The credit is already done + return + + # 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", + ) + self.save() + + for transaction in self.transactions.all(): + transaction.valid = True + transaction.created_at = datetime.now() + transaction.save() + + def delete(self, **kwargs): + """ + Deleting a SogeCredit is equivalent to say that the Société générale didn't pay. + Treasurers must know what they do, this is difficult to undo this operation. + With Great Power Comes Great Responsibility... + """ + self.invalidate() + for transaction in self.transactions.all(): + transaction.valid = True + transaction.created_at = datetime.now() + transaction.save() + super().delete(**kwargs) + + class Meta: + verbose_name = _("Credit from the Société générale") + verbose_name_plural = _("Credits from the Société générale") diff --git a/apps/treasury/tables.py b/apps/treasury/tables.py index 1ecc04db..9f4e43e6 100644 --- a/apps/treasury/tables.py +++ b/apps/treasury/tables.py @@ -7,7 +7,7 @@ from django_tables2 import A from note.models import SpecialTransaction from note.templatetags.pretty_money import pretty_money -from .models import Invoice, Remittance +from .models import Invoice, Remittance, SogeCredit class InvoiceTable(tables.Table): @@ -101,3 +101,28 @@ class SpecialTransactionTable(tables.Table): model = SpecialTransaction template_name = 'django_tables2/bootstrap4.html' fields = ('id', 'source', 'destination', 'last_name', 'first_name', 'bank', 'amount', 'reason',) + + +class SogeCreditTable(tables.Table): + user = tables.LinkColumn( + 'treasury:manage_soge_credit', + args=[A('pk')], + ) + + amount = tables.Column( + verbose_name=_("Amount"), + ) + + valid = tables.Column( + verbose_name=_("Valid"), + ) + + def render_amount(self, value): + return pretty_money(value) + + def render_valid(self, value): + return _("Yes") if value else _("No") + + class Meta: + model = SogeCredit + fields = ('user', 'amount', 'valid', ) diff --git a/apps/treasury/urls.py b/apps/treasury/urls.py index d44cc414..8606fb5b 100644 --- a/apps/treasury/urls.py +++ b/apps/treasury/urls.py @@ -4,7 +4,8 @@ from django.urls import path from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceRenderView, RemittanceListView,\ - RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView, UnlinkTransactionToRemittanceView + RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView, UnlinkTransactionToRemittanceView,\ + SogeCreditListView, SogeCreditManageView app_name = 'treasury' urlpatterns = [ @@ -21,4 +22,7 @@ urlpatterns = [ path('remittance/link_transaction//', LinkTransactionToRemittanceView.as_view(), name='link_transaction'), path('remittance/unlink_transaction//', UnlinkTransactionToRemittanceView.as_view(), name='unlink_transaction'), + + path('soge-credits/list/', SogeCreditListView.as_view(), name='soge_credits'), + path('soge-credits/manage//', SogeCreditManageView.as_view(), name='manage_soge_credit'), ] diff --git a/apps/treasury/views.py b/apps/treasury/views.py index 8d744443..badcb6cc 100644 --- a/apps/treasury/views.py +++ b/apps/treasury/views.py @@ -10,21 +10,23 @@ from crispy_forms.helper import FormHelper from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import ValidationError from django.db.models import Q +from django.forms import Form from django.http import HttpResponse from django.shortcuts import redirect from django.template.loader import render_to_string from django.urls import reverse_lazy -from django.views.generic import CreateView, UpdateView +from django.views.generic import CreateView, UpdateView, DetailView from django.views.generic.base import View, TemplateView +from django.views.generic.edit import BaseFormView from django_tables2 import SingleTableView -from note.models import SpecialTransaction, NoteSpecial +from note.models import SpecialTransaction, NoteSpecial, Alias from note_kfet.settings.base import BASE_DIR from permission.backends import PermissionBackend from permission.views import ProtectQuerysetMixin from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm -from .models import Invoice, Product, Remittance, SpecialTransactionProxy -from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable +from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit +from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): @@ -307,3 +309,61 @@ class UnlinkTransactionToRemittanceView(LoginRequiredMixin, View): transaction.save() return redirect('treasury:remittance_list') + + +class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableView): + """ + List all Société Générale credits + """ + model = SogeCredit + table_class = SogeCreditTable + + def get_queryset(self, **kwargs): + """ + Filter the table with the given parameter. + :param kwargs: + :return: + """ + qs = super().get_queryset() + if "search" in self.request.GET: + pattern = self.request.GET["search"] + + if not pattern: + return qs.none() + + qs = qs.filter( + Q(user__first_name__iregex=pattern) + | Q(user__last_name__iregex=pattern) + | Q(user__note__alias__name__iregex="^" + pattern) + | Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern)) + ) + else: + qs = qs.none() + + if "valid" in self.request.GET: + q = Q(credit_transaction=None) + if not self.request.GET["valid"]: + q = ~q + qs = qs.filter(q) + + return qs[:20] + + +class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormView, DetailView): + """ + Manage credits from the Société générale. + """ + model = SogeCredit + form_class = Form + + def form_valid(self, form): + if "validate" in form.data: + self.get_object().validate(True) + elif "delete" in form.data: + self.get_object().delete() + return super().form_valid(form) + + def get_success_url(self): + if "validate" in self.request.POST: + return reverse_lazy('treasury:manage_soge_credit', args=(self.get_object().pk,)) + return reverse_lazy('treasury:soge_credits') diff --git a/apps/wei/models.py b/apps/wei/models.py index fb192453..9481fb09 100644 --- a/apps/wei/models.py +++ b/apps/wei/models.py @@ -3,6 +3,7 @@ import json +from django.conf import settings from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext_lazy as _ @@ -312,3 +313,14 @@ class WEIMembership(Membership): ) transaction._force_save = True transaction.save(force_insert=True) + + if self.registration.soge_credit and "treasury" in settings.INSTALLED_APPS: + # If the soge pays, then the transaction is unvalidated in a first time, then submitted for control + # to treasurers. + transaction.refresh_from_db() + from treasury.models import SogeCredit + 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() diff --git a/apps/wei/views.py b/apps/wei/views.py index c79c1296..8ad46508 100644 --- a/apps/wei/views.py +++ b/apps/wei/views.py @@ -73,7 +73,8 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): club = context["club"] club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note)) \ - .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view")).order_by('-id') + .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\ + .order_by('-created_at', '-id') history_table = HistoryTable(club_transactions, prefix="history-") history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1)) context['history_list'] = history_table @@ -742,9 +743,10 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.club.pk}) -class WEISurveyView(BaseFormView, DetailView): +class WEISurveyView(LoginRequiredMixin, BaseFormView, DetailView): """ - Display the survey for the WEI for first + Display the survey for the WEI for first year members. + Warning: this page is accessible for anyone that is connected, the view doesn't extend ProtectQuerySetMixin. """ model = WEIRegistration template_name = "wei/survey.html" @@ -800,7 +802,7 @@ class WEISurveyView(BaseFormView, DetailView): return reverse_lazy('wei:wei_survey', args=(self.get_object().pk,)) -class WEISurveyEndView(TemplateView): +class WEISurveyEndView(LoginRequiredMixin, TemplateView): template_name = "wei/survey_end.html" def get_context_data(self, **kwargs): @@ -810,7 +812,7 @@ class WEISurveyEndView(TemplateView): return context -class WEIClosedView(TemplateView): +class WEIClosedView(LoginRequiredMixin, TemplateView): template_name = "wei/survey_closed.html" def get_context_data(self, **kwargs): diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index a8c23ad5..6d76b2e2 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-21 17:47+0200\n" +"POT-Creation-Date: 2020-04-22 03:07+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -44,10 +44,10 @@ msgid "You can't invite more than 3 people to this activity." msgstr "" #: apps/activity/models.py:23 apps/activity/models.py:48 -#: apps/member/models.py:99 apps/member/models.py:203 -#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24 -#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:237 -#: apps/wei/models.py:61 templates/member/club_info.html:13 +#: apps/member/models.py:100 apps/member/models.py:204 +#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25 +#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:250 +#: apps/wei/models.py:62 templates/member/club_info.html:13 #: templates/member/profile_info.html:14 #: templates/registration/future_profile_detail.html:16 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18 @@ -70,20 +70,21 @@ msgstr "" msgid "activity types" msgstr "" -#: apps/activity/models.py:53 apps/note/models/transactions.py:74 -#: apps/permission/models.py:103 apps/wei/models.py:67 apps/wei/models.py:123 +#: apps/activity/models.py:53 apps/note/models/transactions.py:75 +#: apps/permission/models.py:103 apps/wei/models.py:68 apps/wei/models.py:124 #: templates/activity/activity_detail.html:16 msgid "description" msgstr "" #: apps/activity/models.py:60 apps/note/models/notes.py:164 -#: apps/note/models/transactions.py:64 +#: apps/note/models/transactions.py:65 #: templates/activity/activity_detail.html:19 msgid "type" msgstr "" -#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:224 -#: apps/note/models/notes.py:117 apps/wei/models.py:154 +#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:225 +#: apps/note/models/notes.py:117 apps/treasury/models.py:220 +#: apps/wei/models.py:155 templates/treasury/sogecredit_detail.html:13 #: templates/wei/survey.html:16 msgid "user" msgstr "" @@ -104,7 +105,7 @@ msgstr "" msgid "end date" msgstr "" -#: apps/activity/models.py:93 apps/note/models/transactions.py:139 +#: apps/activity/models.py:93 apps/note/models/transactions.py:140 #: templates/activity/activity_detail.html:47 msgid "valid" msgstr "" @@ -180,7 +181,7 @@ msgstr "" msgid "remove" msgstr "" -#: apps/activity/tables.py:75 apps/treasury/models.py:138 +#: apps/activity/tables.py:75 apps/treasury/models.py:139 msgid "Type" msgstr "" @@ -346,117 +347,109 @@ msgstr "" msgid "registration valid" msgstr "" -#: apps/member/models.py:68 -msgid "Société générale" -msgstr "" - -#: apps/member/models.py:69 -msgid "Has the user ever be paid by the Société générale?" -msgstr "" - -#: apps/member/models.py:74 apps/member/models.py:75 +#: apps/member/models.py:75 apps/member/models.py:76 msgid "user profile" msgstr "" -#: apps/member/models.py:104 templates/member/club_info.html:51 +#: apps/member/models.py:105 templates/member/club_info.html:51 #: templates/registration/future_profile_detail.html:22 #: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24 msgid "email" msgstr "" -#: apps/member/models.py:111 +#: apps/member/models.py:112 msgid "parent club" msgstr "" -#: apps/member/models.py:120 +#: apps/member/models.py:121 msgid "require memberships" msgstr "" -#: apps/member/models.py:121 +#: apps/member/models.py:122 msgid "Uncheck if this club don't require memberships." msgstr "" -#: apps/member/models.py:126 templates/member/club_info.html:35 +#: apps/member/models.py:127 templates/member/club_info.html:35 msgid "membership fee (paid students)" msgstr "" -#: apps/member/models.py:131 templates/member/club_info.html:38 +#: apps/member/models.py:132 templates/member/club_info.html:38 msgid "membership fee (unpaid students)" msgstr "" -#: apps/member/models.py:137 templates/member/club_info.html:28 +#: apps/member/models.py:138 templates/member/club_info.html:28 msgid "membership duration" msgstr "" -#: apps/member/models.py:138 +#: apps/member/models.py:139 msgid "The longest time (in days) a membership can last (NULL = infinite)." msgstr "" -#: apps/member/models.py:145 templates/member/club_info.html:22 +#: apps/member/models.py:146 templates/member/club_info.html:22 msgid "membership start" msgstr "" -#: apps/member/models.py:146 +#: apps/member/models.py:147 msgid "How long after January 1st the members can renew their membership." msgstr "" -#: apps/member/models.py:153 templates/member/club_info.html:25 +#: apps/member/models.py:154 templates/member/club_info.html:25 msgid "membership end" msgstr "" -#: apps/member/models.py:154 +#: apps/member/models.py:155 msgid "" "How long the membership can last after January 1st of the next year after " "members can renew their membership." msgstr "" -#: apps/member/models.py:188 apps/member/models.py:230 +#: apps/member/models.py:189 apps/member/models.py:231 #: apps/note/models/notes.py:139 msgid "club" msgstr "" -#: apps/member/models.py:189 +#: apps/member/models.py:190 msgid "clubs" msgstr "" -#: apps/member/models.py:209 apps/permission/models.py:294 +#: apps/member/models.py:210 apps/permission/models.py:294 msgid "role" msgstr "" -#: apps/member/models.py:210 apps/member/models.py:235 +#: apps/member/models.py:211 apps/member/models.py:236 msgid "roles" msgstr "" -#: apps/member/models.py:240 +#: apps/member/models.py:241 msgid "membership starts on" msgstr "" -#: apps/member/models.py:244 +#: apps/member/models.py:245 msgid "membership ends on" msgstr "" -#: apps/member/models.py:249 +#: apps/member/models.py:250 msgid "fee" msgstr "" -#: apps/member/models.py:267 apps/member/views.py:500 apps/wei/views.py:726 +#: apps/member/models.py:268 apps/member/views.py:494 apps/wei/views.py:726 msgid "User is not a member of the parent club" msgstr "" -#: apps/member/models.py:277 apps/member/views.py:509 +#: apps/member/models.py:278 apps/member/views.py:503 msgid "User is already a member of the club" msgstr "" -#: apps/member/models.py:315 +#: apps/member/models.py:329 #, python-brace-format msgid "Membership of {user} for the club {club}" msgstr "" -#: apps/member/models.py:318 +#: apps/member/models.py:332 msgid "membership" msgstr "" -#: apps/member/models.py:319 +#: apps/member/models.py:333 msgid "memberships" msgstr "" @@ -482,32 +475,32 @@ msgstr "" msgid "Search user" msgstr "" -#: apps/member/views.py:495 apps/wei/views.py:717 +#: apps/member/views.py:489 apps/wei/views.py:717 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." msgstr "" -#: apps/member/views.py:513 +#: apps/member/views.py:507 msgid "The membership must start after {:%m-%d-%Y}." msgstr "" -#: apps/member/views.py:518 +#: apps/member/views.py:512 msgid "The membership must begin before {:%m-%d-%Y}." msgstr "" -#: apps/member/views.py:528 apps/member/views.py:530 apps/member/views.py:532 -#: apps/registration/views.py:327 apps/registration/views.py:329 -#: apps/registration/views.py:331 +#: apps/member/views.py:522 apps/member/views.py:524 apps/member/views.py:526 +#: apps/registration/views.py:288 apps/registration/views.py:290 +#: apps/registration/views.py:292 msgid "This field is required." msgstr "" -#: apps/note/admin.py:120 apps/note/models/transactions.py:99 +#: apps/note/admin.py:120 apps/note/models/transactions.py:100 msgid "source" msgstr "" #: apps/note/admin.py:128 apps/note/admin.py:170 -#: apps/note/models/transactions.py:54 apps/note/models/transactions.py:112 +#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:113 msgid "destination" msgstr "" @@ -549,7 +542,7 @@ msgstr "" msgid "display image" msgstr "" -#: apps/note/models/notes.py:53 apps/note/models/transactions.py:122 +#: apps/note/models/notes.py:53 apps/note/models/transactions.py:123 msgid "created at" msgstr "" @@ -620,97 +613,98 @@ msgstr "" msgid "You can't delete your main alias." msgstr "" -#: apps/note/models/transactions.py:30 +#: apps/note/models/transactions.py:31 msgid "transaction category" msgstr "" -#: apps/note/models/transactions.py:31 +#: apps/note/models/transactions.py:32 msgid "transaction categories" msgstr "" -#: apps/note/models/transactions.py:47 +#: apps/note/models/transactions.py:48 msgid "A template with this name already exist" msgstr "" -#: apps/note/models/transactions.py:58 apps/note/models/transactions.py:130 +#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:131 msgid "amount" msgstr "" -#: apps/note/models/transactions.py:59 +#: apps/note/models/transactions.py:60 msgid "in centimes" msgstr "" -#: apps/note/models/transactions.py:70 +#: apps/note/models/transactions.py:71 msgid "display" msgstr "" -#: apps/note/models/transactions.py:80 +#: apps/note/models/transactions.py:81 msgid "transaction template" msgstr "" -#: apps/note/models/transactions.py:81 +#: apps/note/models/transactions.py:82 msgid "transaction templates" msgstr "" -#: apps/note/models/transactions.py:105 apps/note/models/transactions.py:118 +#: apps/note/models/transactions.py:106 apps/note/models/transactions.py:119 #: apps/note/tables.py:33 apps/note/tables.py:42 msgid "used alias" msgstr "" -#: apps/note/models/transactions.py:126 +#: apps/note/models/transactions.py:127 msgid "quantity" msgstr "" -#: apps/note/models/transactions.py:134 +#: apps/note/models/transactions.py:135 msgid "reason" msgstr "" -#: apps/note/models/transactions.py:144 apps/note/tables.py:95 +#: apps/note/models/transactions.py:145 apps/note/tables.py:95 msgid "invalidity reason" msgstr "" -#: apps/note/models/transactions.py:152 +#: apps/note/models/transactions.py:153 msgid "transaction" msgstr "" -#: apps/note/models/transactions.py:153 +#: apps/note/models/transactions.py:154 +#: templates/treasury/sogecredit_detail.html:16 msgid "transactions" msgstr "" -#: apps/note/models/transactions.py:207 +#: apps/note/models/transactions.py:216 #: templates/activity/activity_entry.html:13 templates/base.html:84 #: templates/note/transaction_form.html:19 #: templates/note/transaction_form.html:145 msgid "Transfer" msgstr "" -#: apps/note/models/transactions.py:227 +#: apps/note/models/transactions.py:240 msgid "Template" msgstr "" -#: apps/note/models/transactions.py:242 +#: apps/note/models/transactions.py:255 msgid "first_name" msgstr "" -#: apps/note/models/transactions.py:247 +#: apps/note/models/transactions.py:260 msgid "bank" msgstr "" -#: apps/note/models/transactions.py:253 +#: apps/note/models/transactions.py:266 #: templates/activity/activity_entry.html:17 #: templates/note/transaction_form.html:24 msgid "Credit" msgstr "" -#: apps/note/models/transactions.py:253 templates/note/transaction_form.html:28 +#: apps/note/models/transactions.py:266 templates/note/transaction_form.html:28 msgid "Debit" msgstr "" -#: apps/note/models/transactions.py:269 apps/note/models/transactions.py:274 +#: apps/note/models/transactions.py:282 apps/note/models/transactions.py:287 msgid "membership transaction" msgstr "" -#: apps/note/models/transactions.py:270 +#: apps/note/models/transactions.py:283 apps/treasury/models.py:226 msgid "membership transactions" msgstr "" @@ -727,6 +721,7 @@ msgid "No reason specified" msgstr "" #: apps/note/tables.py:122 apps/note/tables.py:151 apps/wei/tables.py:66 +#: templates/treasury/sogecredit_detail.html:45 #: templates/wei/weiregistration_confirm_delete.html:32 msgid "Delete" msgstr "" @@ -806,31 +801,31 @@ msgstr "" msgid "Join Kfet Club" msgstr "" -#: apps/registration/views.py:116 +#: apps/registration/views.py:77 msgid "Email validation" msgstr "" -#: apps/registration/views.py:162 +#: apps/registration/views.py:123 msgid "Email validation unsuccessful" msgstr "" -#: apps/registration/views.py:173 +#: apps/registration/views.py:134 msgid "Email validation email sent" msgstr "" -#: apps/registration/views.py:226 +#: apps/registration/views.py:187 msgid "Unregistered users" msgstr "" -#: apps/registration/views.py:293 +#: apps/registration/views.py:254 msgid "You must join the BDE." msgstr "" -#: apps/registration/views.py:315 +#: apps/registration/views.py:276 msgid "You must join BDE club before joining Kfet club." msgstr "" -#: apps/registration/views.py:320 +#: apps/registration/views.py:281 msgid "" "The entered amount is not enough for the memberships, should be at least {}" msgstr "" @@ -863,123 +858,137 @@ msgid "You can't change the type of the remittance." msgstr "" #: apps/treasury/forms.py:127 apps/treasury/tables.py:47 -#: templates/note/transaction_form.html:133 +#: apps/treasury/tables.py:113 templates/note/transaction_form.html:133 #: templates/treasury/remittance_form.html:18 msgid "Amount" msgstr "" -#: apps/treasury/models.py:18 +#: apps/treasury/models.py:19 msgid "Invoice identifier" msgstr "" -#: apps/treasury/models.py:32 +#: apps/treasury/models.py:33 msgid "BDE" msgstr "" -#: apps/treasury/models.py:37 +#: apps/treasury/models.py:38 msgid "Object" msgstr "" -#: apps/treasury/models.py:41 +#: apps/treasury/models.py:42 msgid "Description" msgstr "" -#: apps/treasury/models.py:46 templates/note/transaction_form.html:91 +#: apps/treasury/models.py:47 templates/note/transaction_form.html:91 msgid "Name" msgstr "" -#: apps/treasury/models.py:50 +#: apps/treasury/models.py:51 msgid "Address" msgstr "" -#: apps/treasury/models.py:55 +#: apps/treasury/models.py:56 msgid "Place" msgstr "" -#: apps/treasury/models.py:59 +#: apps/treasury/models.py:60 msgid "Acquitted" msgstr "" -#: apps/treasury/models.py:63 +#: apps/treasury/models.py:64 msgid "invoice" msgstr "" -#: apps/treasury/models.py:64 +#: apps/treasury/models.py:65 msgid "invoices" msgstr "" -#: apps/treasury/models.py:79 +#: apps/treasury/models.py:80 msgid "Designation" msgstr "" -#: apps/treasury/models.py:83 +#: apps/treasury/models.py:84 msgid "Quantity" msgstr "" -#: apps/treasury/models.py:87 +#: apps/treasury/models.py:88 msgid "Unit price" msgstr "" -#: apps/treasury/models.py:103 +#: apps/treasury/models.py:104 msgid "product" msgstr "" -#: apps/treasury/models.py:104 +#: apps/treasury/models.py:105 msgid "products" msgstr "" -#: apps/treasury/models.py:121 +#: apps/treasury/models.py:122 msgid "remittance type" msgstr "" -#: apps/treasury/models.py:122 +#: apps/treasury/models.py:123 msgid "remittance types" msgstr "" -#: apps/treasury/models.py:132 +#: apps/treasury/models.py:133 msgid "Date" msgstr "" -#: apps/treasury/models.py:143 +#: apps/treasury/models.py:144 msgid "Comment" msgstr "" -#: apps/treasury/models.py:148 +#: apps/treasury/models.py:149 msgid "Closed" msgstr "" -#: apps/treasury/models.py:152 +#: apps/treasury/models.py:153 msgid "remittance" msgstr "" -#: apps/treasury/models.py:153 +#: apps/treasury/models.py:154 msgid "remittances" msgstr "" -#: apps/treasury/models.py:185 +#: apps/treasury/models.py:186 msgid "Remittance #{:d}: {}" msgstr "" -#: apps/treasury/models.py:204 apps/treasury/tables.py:76 +#: apps/treasury/models.py:205 apps/treasury/tables.py:76 #: apps/treasury/tables.py:84 templates/treasury/invoice_list.html:13 #: templates/treasury/remittance_list.html:13 +#: templates/treasury/sogecredit_list.html:13 msgid "Remittance" msgstr "" -#: apps/treasury/models.py:208 +#: apps/treasury/models.py:209 msgid "special transaction proxy" msgstr "" -#: apps/treasury/models.py:209 +#: apps/treasury/models.py:210 msgid "special transaction proxies" msgstr "" +#: apps/treasury/models.py:232 +msgid "credit transaction" +msgstr "" + +#: apps/treasury/models.py:294 templates/treasury/sogecredit_detail.html:9 +msgid "Credit from the Société générale" +msgstr "" + +#: apps/treasury/models.py:295 +msgid "Credits from the Société générale" +msgstr "" + #: apps/treasury/tables.py:19 msgid "Invoice #{:d}" msgstr "" #: apps/treasury/tables.py:22 templates/treasury/invoice_list.html:10 #: templates/treasury/remittance_list.html:10 +#: templates/treasury/sogecredit_list.html:10 msgid "Invoice" msgstr "" @@ -999,13 +1008,25 @@ msgstr "" msgid "Remove" msgstr "" -#: apps/wei/apps.py:10 apps/wei/models.py:44 apps/wei/models.py:45 -#: apps/wei/models.py:56 apps/wei/models.py:161 templates/base.html:116 +#: apps/treasury/tables.py:117 +msgid "Valid" +msgstr "" + +#: apps/treasury/tables.py:124 +msgid "Yes" +msgstr "" + +#: apps/treasury/tables.py:124 +msgid "No" +msgstr "" + +#: apps/wei/apps.py:10 apps/wei/models.py:45 apps/wei/models.py:46 +#: apps/wei/models.py:57 apps/wei/models.py:162 templates/base.html:116 msgid "WEI" msgstr "" -#: apps/wei/forms/registration.py:47 apps/wei/models.py:108 -#: apps/wei/models.py:269 +#: apps/wei/forms/registration.py:47 apps/wei/models.py:109 +#: apps/wei/models.py:270 msgid "bus" msgstr "" @@ -1026,7 +1047,7 @@ msgid "" msgstr "" #: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67 -#: apps/wei/models.py:142 +#: apps/wei/models.py:143 msgid "WEI Roles" msgstr "" @@ -1042,155 +1063,156 @@ msgstr "" msgid "Attribute to each first year member a bus for the WEI" msgstr "" -#: apps/wei/models.py:19 templates/wei/weiclub_info.html:23 +#: apps/wei/models.py:20 templates/wei/weiclub_info.html:23 msgid "year" msgstr "" -#: apps/wei/models.py:23 templates/wei/weiclub_info.html:17 +#: apps/wei/models.py:24 templates/wei/weiclub_info.html:17 msgid "date start" msgstr "" -#: apps/wei/models.py:27 templates/wei/weiclub_info.html:20 +#: apps/wei/models.py:28 templates/wei/weiclub_info.html:20 msgid "date end" msgstr "" -#: apps/wei/models.py:72 +#: apps/wei/models.py:73 msgid "survey information" msgstr "" -#: apps/wei/models.py:73 +#: apps/wei/models.py:74 msgid "Information about the survey for new members, encoded in JSON" msgstr "" -#: apps/wei/models.py:95 +#: apps/wei/models.py:96 msgid "Bus" msgstr "" -#: apps/wei/models.py:96 templates/wei/weiclub_tables.html:79 +#: apps/wei/models.py:97 templates/wei/weiclub_tables.html:79 msgid "Buses" msgstr "" -#: apps/wei/models.py:116 +#: apps/wei/models.py:117 msgid "color" msgstr "" -#: apps/wei/models.py:117 +#: apps/wei/models.py:118 msgid "The color of the T-Shirt, stored with its number equivalent" msgstr "" -#: apps/wei/models.py:131 +#: apps/wei/models.py:132 msgid "Bus team" msgstr "" -#: apps/wei/models.py:132 +#: apps/wei/models.py:133 msgid "Bus teams" msgstr "" -#: apps/wei/models.py:141 +#: apps/wei/models.py:142 msgid "WEI Role" msgstr "" -#: apps/wei/models.py:166 +#: apps/wei/models.py:167 msgid "Credit from Société générale" msgstr "" -#: apps/wei/models.py:171 +#: apps/wei/models.py:172 msgid "Caution check given" msgstr "" -#: apps/wei/models.py:175 templates/wei/weimembership_form.html:56 +#: apps/wei/models.py:176 templates/wei/weimembership_form.html:56 msgid "birth date" msgstr "" -#: apps/wei/models.py:181 +#: apps/wei/models.py:182 msgid "Male" msgstr "" -#: apps/wei/models.py:182 +#: apps/wei/models.py:183 msgid "Female" msgstr "" -#: apps/wei/models.py:183 +#: apps/wei/models.py:184 msgid "Non binary" msgstr "" -#: apps/wei/models.py:185 templates/wei/weimembership_form.html:53 +#: apps/wei/models.py:186 templates/wei/weimembership_form.html:53 msgid "gender" msgstr "" -#: apps/wei/models.py:191 templates/wei/weimembership_form.html:59 +#: apps/wei/models.py:192 templates/wei/weimembership_form.html:59 msgid "health issues" msgstr "" -#: apps/wei/models.py:196 templates/wei/weimembership_form.html:62 +#: apps/wei/models.py:197 templates/wei/weimembership_form.html:62 msgid "emergency contact name" msgstr "" -#: apps/wei/models.py:201 templates/wei/weimembership_form.html:65 +#: apps/wei/models.py:202 templates/wei/weimembership_form.html:65 msgid "emergency contact phone" msgstr "" -#: apps/wei/models.py:206 templates/wei/weimembership_form.html:68 +#: apps/wei/models.py:207 templates/wei/weimembership_form.html:68 msgid "" "Register on the mailing list to stay informed of the events of the campus (1 " "mail/week)" msgstr "" -#: apps/wei/models.py:211 templates/wei/weimembership_form.html:71 +#: apps/wei/models.py:212 templates/wei/weimembership_form.html:71 msgid "" "Register on the mailing list to stay informed of the sport events of the " "campus (1 mail/week)" msgstr "" -#: apps/wei/models.py:216 templates/wei/weimembership_form.html:74 +#: apps/wei/models.py:217 templates/wei/weimembership_form.html:74 msgid "" "Register on the mailing list to stay informed of the art events of the " "campus (1 mail/week)" msgstr "" -#: apps/wei/models.py:221 templates/wei/weimembership_form.html:50 +#: apps/wei/models.py:222 templates/wei/weimembership_form.html:50 msgid "first year" msgstr "" -#: apps/wei/models.py:222 +#: apps/wei/models.py:223 msgid "Tells if the user is new in the school." msgstr "" -#: apps/wei/models.py:227 +#: apps/wei/models.py:228 msgid "registration information" msgstr "" -#: apps/wei/models.py:228 +#: apps/wei/models.py:229 msgid "" "Information about the registration (buses for old members, survey fot the " "new members), encoded in JSON" msgstr "" -#: apps/wei/models.py:259 +#: apps/wei/models.py:260 msgid "WEI User" msgstr "" -#: apps/wei/models.py:260 +#: apps/wei/models.py:261 msgid "WEI Users" msgstr "" -#: apps/wei/models.py:279 +#: apps/wei/models.py:280 msgid "team" msgstr "" -#: apps/wei/models.py:289 +#: apps/wei/models.py:290 msgid "WEI registration" msgstr "" -#: apps/wei/models.py:293 +#: apps/wei/models.py:294 msgid "WEI membership" msgstr "" -#: apps/wei/models.py:294 +#: apps/wei/models.py:295 msgid "WEI memberships" msgstr "" #: apps/wei/tables.py:53 apps/wei/tables.py:54 +#: templates/treasury/sogecredit_detail.html:44 msgid "Validate" msgstr "" @@ -1233,7 +1255,7 @@ msgstr "" msgid "This user didn't give her/his caution check." msgstr "" -#: apps/wei/views.py:789 apps/wei/views.py:809 apps/wei/views.py:819 +#: apps/wei/views.py:790 apps/wei/views.py:810 apps/wei/views.py:820 #: templates/wei/survey.html:12 templates/wei/survey_closed.html:12 #: templates/wei/survey_end.html:12 msgid "Survey WEI" @@ -1745,22 +1767,16 @@ msgid "Reset my password" msgstr "" #: templates/registration/signup.html:5 templates/registration/signup.html:8 -#: templates/registration/signup.html:28 +#: templates/registration/signup.html:19 msgid "Sign up" msgstr "" #: templates/registration/signup.html:11 msgid "" -"\n" -" If you already signed up, your registration is taken into " -"account. The BDE must validate your account before\n" -" your can log in. You have to go to the Kfet and pay the " -"registration fee. You must also validate your email\n" -" address by following the link you received. If you forgot to " -"register to the WEI, then you can pre-register\n" -" to the WEI after your account get validated, so please go to the " -"Kfet.\n" -" " +"If you already signed up, your registration is taken into account. The BDE " +"must validate your account before your can log in. You have to go to the " +"Kfet and pay the registration fee. You must also validate your email address " +"by following the link you received." msgstr "" #: templates/treasury/invoice_form.html:6 @@ -1775,7 +1791,13 @@ msgstr "" msgid "Remove product" msgstr "" -#: templates/treasury/invoice_list.html:21 +#: templates/treasury/invoice_list.html:16 +#: templates/treasury/remittance_list.html:16 +#: templates/treasury/sogecredit_list.html:16 +msgid "Société générale credits" +msgstr "" + +#: templates/treasury/invoice_list.html:24 msgid "New invoice" msgstr "" @@ -1800,38 +1822,80 @@ msgstr "" msgid "There is no transaction linked with this remittance." msgstr "" -#: templates/treasury/remittance_list.html:19 +#: templates/treasury/remittance_list.html:22 msgid "Opened remittances" msgstr "" -#: templates/treasury/remittance_list.html:24 +#: templates/treasury/remittance_list.html:27 msgid "There is no opened remittance." msgstr "" -#: templates/treasury/remittance_list.html:28 +#: templates/treasury/remittance_list.html:31 msgid "New remittance" msgstr "" -#: templates/treasury/remittance_list.html:32 +#: templates/treasury/remittance_list.html:35 msgid "Transfers without remittances" msgstr "" -#: templates/treasury/remittance_list.html:37 +#: templates/treasury/remittance_list.html:40 msgid "There is no transaction without any linked remittance." msgstr "" -#: templates/treasury/remittance_list.html:43 +#: templates/treasury/remittance_list.html:46 msgid "Transfers with opened remittances" msgstr "" -#: templates/treasury/remittance_list.html:48 +#: templates/treasury/remittance_list.html:51 msgid "There is no transaction with an opened linked remittance." msgstr "" -#: templates/treasury/remittance_list.html:54 +#: templates/treasury/remittance_list.html:57 msgid "Closed remittances" msgstr "" +#: templates/treasury/sogecredit_detail.html:23 +msgid "total amount" +msgstr "" + +#: templates/treasury/sogecredit_detail.html:29 +msgid "" +"Warning: Validating this credit implies that all membership transactions " +"will be validated." +msgstr "" + +#: templates/treasury/sogecredit_detail.html:30 +msgid "" +"If you delete this credit, there all membership transactions will be also " +"validated, but no credit will be operated." +msgstr "" + +#: templates/treasury/sogecredit_detail.html:31 +msgid "" +"If this credit is validated, then the user won't be able to ask for a credit " +"from the Société générale." +msgstr "" + +#: templates/treasury/sogecredit_detail.html:32 +msgid "If you think there is an error, please contact the \"respos info\"." +msgstr "" + +#: templates/treasury/sogecredit_detail.html:38 +msgid "This credit is already validated." +msgstr "" + +#: templates/treasury/sogecredit_detail.html:49 +msgid "Return to credit list" +msgstr "" + +#: templates/treasury/sogecredit_list.html:26 +msgid "Filter with unvalidated credits only" +msgstr "" + +#: templates/treasury/sogecredit_list.html:36 +msgid "There is no matched user that have asked for a Société générale credit." +msgstr "" + #: templates/wei/bus_tables.html:16 templates/wei/busteam_tables.html:16 msgid "Add team" msgstr "" diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 69de359f..0d81f423 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-21 17:47+0200\n" +"POT-Creation-Date: 2020-04-22 03:07+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -40,10 +40,10 @@ msgid "You can't invite more than 3 people to this activity." msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité." #: apps/activity/models.py:23 apps/activity/models.py:48 -#: apps/member/models.py:99 apps/member/models.py:203 -#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24 -#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:237 -#: apps/wei/models.py:61 templates/member/club_info.html:13 +#: apps/member/models.py:100 apps/member/models.py:204 +#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25 +#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:250 +#: apps/wei/models.py:62 templates/member/club_info.html:13 #: templates/member/profile_info.html:14 #: templates/registration/future_profile_detail.html:16 #: templates/wei/weiclub_info.html:13 templates/wei/weimembership_form.html:18 @@ -66,20 +66,21 @@ msgstr "type d'activité" msgid "activity types" msgstr "types d'activité" -#: apps/activity/models.py:53 apps/note/models/transactions.py:74 -#: apps/permission/models.py:103 apps/wei/models.py:67 apps/wei/models.py:123 +#: apps/activity/models.py:53 apps/note/models/transactions.py:75 +#: apps/permission/models.py:103 apps/wei/models.py:68 apps/wei/models.py:124 #: templates/activity/activity_detail.html:16 msgid "description" msgstr "description" #: apps/activity/models.py:60 apps/note/models/notes.py:164 -#: apps/note/models/transactions.py:64 +#: apps/note/models/transactions.py:65 #: templates/activity/activity_detail.html:19 msgid "type" msgstr "type" -#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:224 -#: apps/note/models/notes.py:117 apps/wei/models.py:154 +#: apps/activity/models.py:66 apps/logs/models.py:21 apps/member/models.py:225 +#: apps/note/models/notes.py:117 apps/treasury/models.py:220 +#: apps/wei/models.py:155 templates/treasury/sogecredit_detail.html:13 #: templates/wei/survey.html:16 msgid "user" msgstr "utilisateur" @@ -100,7 +101,7 @@ msgstr "date de début" msgid "end date" msgstr "date de fin" -#: apps/activity/models.py:93 apps/note/models/transactions.py:139 +#: apps/activity/models.py:93 apps/note/models/transactions.py:140 #: templates/activity/activity_detail.html:47 msgid "valid" msgstr "valide" @@ -176,7 +177,7 @@ msgstr "Entré le " msgid "remove" msgstr "supprimer" -#: apps/activity/tables.py:75 apps/treasury/models.py:138 +#: apps/activity/tables.py:75 apps/treasury/models.py:139 msgid "Type" msgstr "Type" @@ -342,67 +343,59 @@ msgstr "adresse email confirmée" msgid "registration valid" msgstr "inscription valid" -#: apps/member/models.py:68 -msgid "Société générale" -msgstr "Société générale" - -#: apps/member/models.py:69 -msgid "Has the user ever be paid by the Société générale?" -msgstr "Est-ce que l'utilisateur a déjà été payé par la Société Générale ?" - -#: apps/member/models.py:74 apps/member/models.py:75 +#: apps/member/models.py:75 apps/member/models.py:76 msgid "user profile" msgstr "profil utilisateur" -#: apps/member/models.py:104 templates/member/club_info.html:51 +#: apps/member/models.py:105 templates/member/club_info.html:51 #: templates/registration/future_profile_detail.html:22 #: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24 msgid "email" msgstr "courriel" -#: apps/member/models.py:111 +#: apps/member/models.py:112 msgid "parent club" msgstr "club parent" -#: apps/member/models.py:120 +#: apps/member/models.py:121 msgid "require memberships" msgstr "nécessite des adhésions" -#: apps/member/models.py:121 +#: apps/member/models.py:122 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:126 templates/member/club_info.html:35 +#: apps/member/models.py:127 templates/member/club_info.html:35 msgid "membership fee (paid students)" msgstr "cotisation pour adhérer (normalien élève)" -#: apps/member/models.py:131 templates/member/club_info.html:38 +#: apps/member/models.py:132 templates/member/club_info.html:38 msgid "membership fee (unpaid students)" msgstr "cotisation pour adhérer (normalien étudiant)" -#: apps/member/models.py:137 templates/member/club_info.html:28 +#: apps/member/models.py:138 templates/member/club_info.html:28 msgid "membership duration" msgstr "durée de l'adhésion" -#: apps/member/models.py:138 +#: apps/member/models.py:139 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:145 templates/member/club_info.html:22 +#: apps/member/models.py:146 templates/member/club_info.html:22 msgid "membership start" msgstr "début de l'adhésion" -#: apps/member/models.py:146 +#: apps/member/models.py:147 msgid "How long after January 1st the members can renew their membership." msgstr "" "Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur " "adhésion." -#: apps/member/models.py:153 templates/member/club_info.html:25 +#: apps/member/models.py:154 templates/member/club_info.html:25 msgid "membership end" msgstr "fin de l'adhésion" -#: apps/member/models.py:154 +#: apps/member/models.py:155 msgid "" "How long the membership can last after January 1st of the next year after " "members can renew their membership." @@ -410,53 +403,53 @@ msgstr "" "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année " "suivante avant que les adhérents peuvent renouveler leur adhésion." -#: apps/member/models.py:188 apps/member/models.py:230 +#: apps/member/models.py:189 apps/member/models.py:231 #: apps/note/models/notes.py:139 msgid "club" msgstr "club" -#: apps/member/models.py:189 +#: apps/member/models.py:190 msgid "clubs" msgstr "clubs" -#: apps/member/models.py:209 apps/permission/models.py:294 +#: apps/member/models.py:210 apps/permission/models.py:294 msgid "role" msgstr "rôle" -#: apps/member/models.py:210 apps/member/models.py:235 +#: apps/member/models.py:211 apps/member/models.py:236 msgid "roles" msgstr "rôles" -#: apps/member/models.py:240 +#: apps/member/models.py:241 msgid "membership starts on" msgstr "l'adhésion commence le" -#: apps/member/models.py:244 +#: apps/member/models.py:245 msgid "membership ends on" msgstr "l'adhésion finit le" -#: apps/member/models.py:249 +#: apps/member/models.py:250 msgid "fee" msgstr "cotisation" -#: apps/member/models.py:267 apps/member/views.py:500 apps/wei/views.py:726 +#: apps/member/models.py:268 apps/member/views.py:494 apps/wei/views.py:726 msgid "User is not a member of the parent club" msgstr "L'utilisateur n'est pas membre du club parent" -#: apps/member/models.py:277 apps/member/views.py:509 +#: apps/member/models.py:278 apps/member/views.py:503 msgid "User is already a member of the club" msgstr "L'utilisateur est déjà membre du club" -#: apps/member/models.py:315 +#: apps/member/models.py:329 #, python-brace-format msgid "Membership of {user} for the club {club}" msgstr "Adhésion de {user} pour le club {club}" -#: apps/member/models.py:318 +#: apps/member/models.py:332 msgid "membership" msgstr "adhésion" -#: apps/member/models.py:319 +#: apps/member/models.py:333 msgid "memberships" msgstr "adhésions" @@ -482,7 +475,7 @@ msgstr "Un alias avec un nom similaire existe déjà." msgid "Search user" msgstr "Chercher un utilisateur" -#: apps/member/views.py:495 apps/wei/views.py:717 +#: apps/member/views.py:489 apps/wei/views.py:717 msgid "" "This user don't have enough money to join this club, and can't have a " "negative balance." @@ -490,26 +483,26 @@ 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:513 +#: apps/member/views.py:507 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:518 +#: apps/member/views.py:512 msgid "The membership must begin before {:%m-%d-%Y}." msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}." -#: apps/member/views.py:528 apps/member/views.py:530 apps/member/views.py:532 -#: apps/registration/views.py:327 apps/registration/views.py:329 -#: apps/registration/views.py:331 +#: apps/member/views.py:522 apps/member/views.py:524 apps/member/views.py:526 +#: apps/registration/views.py:288 apps/registration/views.py:290 +#: apps/registration/views.py:292 msgid "This field is required." msgstr "Ce champ est requis." -#: apps/note/admin.py:120 apps/note/models/transactions.py:99 +#: apps/note/admin.py:120 apps/note/models/transactions.py:100 msgid "source" msgstr "source" #: apps/note/admin.py:128 apps/note/admin.py:170 -#: apps/note/models/transactions.py:54 apps/note/models/transactions.py:112 +#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:113 msgid "destination" msgstr "destination" @@ -552,7 +545,7 @@ msgstr "" msgid "display image" msgstr "image affichée" -#: apps/note/models/notes.py:53 apps/note/models/transactions.py:122 +#: apps/note/models/notes.py:53 apps/note/models/transactions.py:123 msgid "created at" msgstr "créée le" @@ -623,97 +616,98 @@ msgstr "Un alias avec un nom similaire existe déjà : {}" msgid "You can't delete your main alias." msgstr "Vous ne pouvez pas supprimer votre alias principal." -#: apps/note/models/transactions.py:30 +#: apps/note/models/transactions.py:31 msgid "transaction category" msgstr "catégorie de transaction" -#: apps/note/models/transactions.py:31 +#: apps/note/models/transactions.py:32 msgid "transaction categories" msgstr "catégories de transaction" -#: apps/note/models/transactions.py:47 +#: apps/note/models/transactions.py:48 msgid "A template with this name already exist" msgstr "Un modèle de transaction avec un nom similaire existe déjà." -#: apps/note/models/transactions.py:58 apps/note/models/transactions.py:130 +#: apps/note/models/transactions.py:59 apps/note/models/transactions.py:131 msgid "amount" msgstr "montant" -#: apps/note/models/transactions.py:59 +#: apps/note/models/transactions.py:60 msgid "in centimes" msgstr "en centimes" -#: apps/note/models/transactions.py:70 +#: apps/note/models/transactions.py:71 msgid "display" msgstr "afficher" -#: apps/note/models/transactions.py:80 +#: apps/note/models/transactions.py:81 msgid "transaction template" msgstr "modèle de transaction" -#: apps/note/models/transactions.py:81 +#: apps/note/models/transactions.py:82 msgid "transaction templates" msgstr "modèles de transaction" -#: apps/note/models/transactions.py:105 apps/note/models/transactions.py:118 +#: apps/note/models/transactions.py:106 apps/note/models/transactions.py:119 #: apps/note/tables.py:33 apps/note/tables.py:42 msgid "used alias" msgstr "alias utilisé" -#: apps/note/models/transactions.py:126 +#: apps/note/models/transactions.py:127 msgid "quantity" msgstr "quantité" -#: apps/note/models/transactions.py:134 +#: apps/note/models/transactions.py:135 msgid "reason" msgstr "raison" -#: apps/note/models/transactions.py:144 apps/note/tables.py:95 +#: apps/note/models/transactions.py:145 apps/note/tables.py:95 msgid "invalidity reason" msgstr "Motif d'invalidité" -#: apps/note/models/transactions.py:152 +#: apps/note/models/transactions.py:153 msgid "transaction" msgstr "transaction" -#: apps/note/models/transactions.py:153 +#: apps/note/models/transactions.py:154 +#: templates/treasury/sogecredit_detail.html:16 msgid "transactions" msgstr "transactions" -#: apps/note/models/transactions.py:207 +#: apps/note/models/transactions.py:216 #: templates/activity/activity_entry.html:13 templates/base.html:84 #: templates/note/transaction_form.html:19 #: templates/note/transaction_form.html:145 msgid "Transfer" msgstr "Virement" -#: apps/note/models/transactions.py:227 +#: apps/note/models/transactions.py:240 msgid "Template" msgstr "Bouton" -#: apps/note/models/transactions.py:242 +#: apps/note/models/transactions.py:255 msgid "first_name" msgstr "prénom" -#: apps/note/models/transactions.py:247 +#: apps/note/models/transactions.py:260 msgid "bank" msgstr "banque" -#: apps/note/models/transactions.py:253 +#: apps/note/models/transactions.py:266 #: templates/activity/activity_entry.html:17 #: templates/note/transaction_form.html:24 msgid "Credit" msgstr "Crédit" -#: apps/note/models/transactions.py:253 templates/note/transaction_form.html:28 +#: apps/note/models/transactions.py:266 templates/note/transaction_form.html:28 msgid "Debit" msgstr "Débit" -#: apps/note/models/transactions.py:269 apps/note/models/transactions.py:274 +#: apps/note/models/transactions.py:282 apps/note/models/transactions.py:287 msgid "membership transaction" msgstr "Transaction d'adhésion" -#: apps/note/models/transactions.py:270 +#: apps/note/models/transactions.py:283 apps/treasury/models.py:226 msgid "membership transactions" msgstr "Transactions d'adhésion" @@ -730,6 +724,7 @@ msgid "No reason specified" msgstr "Pas de motif spécifié" #: apps/note/tables.py:122 apps/note/tables.py:151 apps/wei/tables.py:66 +#: templates/treasury/sogecredit_detail.html:45 #: templates/wei/weiregistration_confirm_delete.html:32 msgid "Delete" msgstr "Supprimer" @@ -812,31 +807,31 @@ msgstr "Adhérer au club BDE" msgid "Join Kfet Club" msgstr "Adhérer au club Kfet" -#: apps/registration/views.py:116 +#: apps/registration/views.py:77 msgid "Email validation" msgstr "Validation de l'adresse mail" -#: apps/registration/views.py:162 +#: apps/registration/views.py:123 msgid "Email validation unsuccessful" msgstr " La validation de l'adresse mail a échoué" -#: apps/registration/views.py:173 +#: apps/registration/views.py:134 msgid "Email validation email sent" msgstr "L'email de vérification de l'adresse email a bien été envoyé." -#: apps/registration/views.py:226 +#: apps/registration/views.py:187 msgid "Unregistered users" msgstr "Utilisateurs en attente d'inscription" -#: apps/registration/views.py:293 +#: apps/registration/views.py:254 msgid "You must join the BDE." msgstr "Vous devez adhérer au BDE." -#: apps/registration/views.py:315 +#: apps/registration/views.py:276 msgid "You must join BDE club before joining Kfet club." msgstr "Vous devez adhérer au club BDE avant d'adhérer au club Kfet." -#: apps/registration/views.py:320 +#: apps/registration/views.py:281 msgid "" "The entered amount is not enough for the memberships, should be at least {}" msgstr "" @@ -871,123 +866,137 @@ 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:127 apps/treasury/tables.py:47 -#: templates/note/transaction_form.html:133 +#: apps/treasury/tables.py:113 templates/note/transaction_form.html:133 #: templates/treasury/remittance_form.html:18 msgid "Amount" msgstr "Montant" -#: apps/treasury/models.py:18 +#: apps/treasury/models.py:19 msgid "Invoice identifier" msgstr "Numéro de facture" -#: apps/treasury/models.py:32 +#: apps/treasury/models.py:33 msgid "BDE" msgstr "BDE" -#: apps/treasury/models.py:37 +#: apps/treasury/models.py:38 msgid "Object" msgstr "Objet" -#: apps/treasury/models.py:41 +#: apps/treasury/models.py:42 msgid "Description" msgstr "Description" -#: apps/treasury/models.py:46 templates/note/transaction_form.html:91 +#: apps/treasury/models.py:47 templates/note/transaction_form.html:91 msgid "Name" msgstr "Nom" -#: apps/treasury/models.py:50 +#: apps/treasury/models.py:51 msgid "Address" msgstr "Adresse" -#: apps/treasury/models.py:55 +#: apps/treasury/models.py:56 msgid "Place" msgstr "Lieu" -#: apps/treasury/models.py:59 +#: apps/treasury/models.py:60 msgid "Acquitted" msgstr "Acquittée" -#: apps/treasury/models.py:63 +#: apps/treasury/models.py:64 msgid "invoice" msgstr "facture" -#: apps/treasury/models.py:64 +#: apps/treasury/models.py:65 msgid "invoices" msgstr "factures" -#: apps/treasury/models.py:79 +#: apps/treasury/models.py:80 msgid "Designation" msgstr "Désignation" -#: apps/treasury/models.py:83 +#: apps/treasury/models.py:84 msgid "Quantity" msgstr "Quantité" -#: apps/treasury/models.py:87 +#: apps/treasury/models.py:88 msgid "Unit price" msgstr "Prix unitaire" -#: apps/treasury/models.py:103 +#: apps/treasury/models.py:104 msgid "product" msgstr "produit" -#: apps/treasury/models.py:104 +#: apps/treasury/models.py:105 msgid "products" msgstr "produits" -#: apps/treasury/models.py:121 +#: apps/treasury/models.py:122 msgid "remittance type" msgstr "type de remise" -#: apps/treasury/models.py:122 +#: apps/treasury/models.py:123 msgid "remittance types" msgstr "types de remises" -#: apps/treasury/models.py:132 +#: apps/treasury/models.py:133 msgid "Date" msgstr "Date" -#: apps/treasury/models.py:143 +#: apps/treasury/models.py:144 msgid "Comment" msgstr "Commentaire" -#: apps/treasury/models.py:148 +#: apps/treasury/models.py:149 msgid "Closed" msgstr "Fermée" -#: apps/treasury/models.py:152 +#: apps/treasury/models.py:153 msgid "remittance" msgstr "remise" -#: apps/treasury/models.py:153 +#: apps/treasury/models.py:154 msgid "remittances" msgstr "remises" -#: apps/treasury/models.py:185 +#: apps/treasury/models.py:186 msgid "Remittance #{:d}: {}" msgstr "Remise n°{:d} : {}" -#: apps/treasury/models.py:204 apps/treasury/tables.py:76 +#: apps/treasury/models.py:205 apps/treasury/tables.py:76 #: apps/treasury/tables.py:84 templates/treasury/invoice_list.html:13 #: templates/treasury/remittance_list.html:13 +#: templates/treasury/sogecredit_list.html:13 msgid "Remittance" msgstr "Remise" -#: apps/treasury/models.py:208 +#: apps/treasury/models.py:209 msgid "special transaction proxy" msgstr "Proxy de transaction spéciale" -#: apps/treasury/models.py:209 +#: apps/treasury/models.py:210 msgid "special transaction proxies" msgstr "Proxys de transactions spéciales" +#: apps/treasury/models.py:232 +msgid "credit transaction" +msgstr "transaction de crédit" + +#: apps/treasury/models.py:294 templates/treasury/sogecredit_detail.html:9 +msgid "Credit from the Société générale" +msgstr "Crédit de la Société générale" + +#: apps/treasury/models.py:295 +msgid "Credits from the Société générale" +msgstr "Crédits de la Société générale" + #: apps/treasury/tables.py:19 msgid "Invoice #{:d}" msgstr "Facture n°{:d}" #: apps/treasury/tables.py:22 templates/treasury/invoice_list.html:10 #: templates/treasury/remittance_list.html:10 +#: templates/treasury/sogecredit_list.html:10 msgid "Invoice" msgstr "Facture" @@ -1007,13 +1016,25 @@ msgstr "Ajouter" msgid "Remove" msgstr "supprimer" -#: apps/wei/apps.py:10 apps/wei/models.py:44 apps/wei/models.py:45 -#: apps/wei/models.py:56 apps/wei/models.py:161 templates/base.html:116 +#: apps/treasury/tables.py:117 +msgid "Valid" +msgstr "Valide" + +#: apps/treasury/tables.py:124 +msgid "Yes" +msgstr "Oui" + +#: apps/treasury/tables.py:124 +msgid "No" +msgstr "Non" + +#: apps/wei/apps.py:10 apps/wei/models.py:45 apps/wei/models.py:46 +#: apps/wei/models.py:57 apps/wei/models.py:162 templates/base.html:116 msgid "WEI" msgstr "WEI" -#: apps/wei/forms/registration.py:47 apps/wei/models.py:108 -#: apps/wei/models.py:269 +#: apps/wei/forms/registration.py:47 apps/wei/models.py:109 +#: apps/wei/models.py:270 msgid "bus" msgstr "Bus" @@ -1039,7 +1060,7 @@ msgstr "" "bus ou électron libre)" #: apps/wei/forms/registration.py:61 apps/wei/forms/registration.py:67 -#: apps/wei/models.py:142 +#: apps/wei/models.py:143 msgid "WEI Roles" msgstr "Rôles au WEI" @@ -1055,97 +1076,97 @@ msgstr "Cette équipe n'appartient pas à ce bus." msgid "Attribute to each first year member a bus for the WEI" msgstr "Attribuer à chaque première année un bus pour le WEI" -#: apps/wei/models.py:19 templates/wei/weiclub_info.html:23 +#: apps/wei/models.py:20 templates/wei/weiclub_info.html:23 msgid "year" msgstr "année" -#: apps/wei/models.py:23 templates/wei/weiclub_info.html:17 +#: apps/wei/models.py:24 templates/wei/weiclub_info.html:17 msgid "date start" msgstr "début" -#: apps/wei/models.py:27 templates/wei/weiclub_info.html:20 +#: apps/wei/models.py:28 templates/wei/weiclub_info.html:20 msgid "date end" msgstr "fin" -#: apps/wei/models.py:72 +#: apps/wei/models.py:73 msgid "survey information" msgstr "informations sur le questionnaire" -#: apps/wei/models.py:73 +#: apps/wei/models.py:74 msgid "Information about the survey for new members, encoded in JSON" msgstr "" "Informations sur le sondage pour les nouveaux membres, encodées en JSON" -#: apps/wei/models.py:95 +#: apps/wei/models.py:96 msgid "Bus" msgstr "Bus" -#: apps/wei/models.py:96 templates/wei/weiclub_tables.html:79 +#: apps/wei/models.py:97 templates/wei/weiclub_tables.html:79 msgid "Buses" msgstr "Bus" -#: apps/wei/models.py:116 +#: apps/wei/models.py:117 msgid "color" msgstr "couleur" -#: apps/wei/models.py:117 +#: apps/wei/models.py:118 msgid "The color of the T-Shirt, stored with its number equivalent" msgstr "" "La couleur du T-Shirt, stocké sous la forme de son équivalent numérique" -#: apps/wei/models.py:131 +#: apps/wei/models.py:132 msgid "Bus team" msgstr "Équipe de bus" -#: apps/wei/models.py:132 +#: apps/wei/models.py:133 msgid "Bus teams" msgstr "Équipes de bus" -#: apps/wei/models.py:141 +#: apps/wei/models.py:142 msgid "WEI Role" msgstr "Rôle au WEI" -#: apps/wei/models.py:166 +#: apps/wei/models.py:167 msgid "Credit from Société générale" msgstr "Crédit de la Société générale" -#: apps/wei/models.py:171 +#: apps/wei/models.py:172 msgid "Caution check given" msgstr "Chèque de caution donné" -#: apps/wei/models.py:175 templates/wei/weimembership_form.html:56 +#: apps/wei/models.py:176 templates/wei/weimembership_form.html:56 msgid "birth date" msgstr "date de naissance" -#: apps/wei/models.py:181 +#: apps/wei/models.py:182 msgid "Male" msgstr "Homme" -#: apps/wei/models.py:182 +#: apps/wei/models.py:183 msgid "Female" msgstr "Femme" -#: apps/wei/models.py:183 +#: apps/wei/models.py:184 msgid "Non binary" msgstr "Non-binaire" -#: apps/wei/models.py:185 templates/wei/weimembership_form.html:53 +#: apps/wei/models.py:186 templates/wei/weimembership_form.html:53 msgid "gender" msgstr "genre" -#: apps/wei/models.py:191 templates/wei/weimembership_form.html:59 +#: apps/wei/models.py:192 templates/wei/weimembership_form.html:59 msgid "health issues" msgstr "problèmes de santé" -#: apps/wei/models.py:196 templates/wei/weimembership_form.html:62 +#: apps/wei/models.py:197 templates/wei/weimembership_form.html:62 msgid "emergency contact name" msgstr "Nom du contact en cas d'urgence" -#: apps/wei/models.py:201 templates/wei/weimembership_form.html:65 +#: apps/wei/models.py:202 templates/wei/weimembership_form.html:65 msgid "emergency contact phone" msgstr "Téléphone du contact en cas d'urgence" -#: apps/wei/models.py:206 templates/wei/weimembership_form.html:68 +#: apps/wei/models.py:207 templates/wei/weimembership_form.html:68 msgid "" "Register on the mailing list to stay informed of the events of the campus (1 " "mail/week)" @@ -1153,7 +1174,7 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des événements sur " "le campus (1 mail par semaine)" -#: apps/wei/models.py:211 templates/wei/weimembership_form.html:71 +#: apps/wei/models.py:212 templates/wei/weimembership_form.html:71 msgid "" "Register on the mailing list to stay informed of the sport events of the " "campus (1 mail/week)" @@ -1161,7 +1182,7 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des actualités " "sportives sur le campus (1 mail par semaine)" -#: apps/wei/models.py:216 templates/wei/weimembership_form.html:74 +#: apps/wei/models.py:217 templates/wei/weimembership_form.html:74 msgid "" "Register on the mailing list to stay informed of the art events of the " "campus (1 mail/week)" @@ -1169,19 +1190,19 @@ msgstr "" "S'inscrire sur la liste de diffusion pour rester informé des actualités " "artistiques sur le campus (1 mail par semaine)" -#: apps/wei/models.py:221 templates/wei/weimembership_form.html:50 +#: apps/wei/models.py:222 templates/wei/weimembership_form.html:50 msgid "first year" msgstr "première année" -#: apps/wei/models.py:222 +#: apps/wei/models.py:223 msgid "Tells if the user is new in the school." msgstr "Indique si l'utilisateur est nouveau dans l'école." -#: apps/wei/models.py:227 +#: apps/wei/models.py:228 msgid "registration information" msgstr "informations sur l'inscription" -#: apps/wei/models.py:228 +#: apps/wei/models.py:229 msgid "" "Information about the registration (buses for old members, survey fot the " "new members), encoded in JSON" @@ -1189,31 +1210,32 @@ msgstr "" "Informations sur l'inscription (bus pour les 2A+, questionnaire pour les " "1A), encodées en JSON" -#: apps/wei/models.py:259 +#: apps/wei/models.py:260 msgid "WEI User" msgstr "Participant au WEI" -#: apps/wei/models.py:260 +#: apps/wei/models.py:261 msgid "WEI Users" msgstr "Participants au WEI" -#: apps/wei/models.py:279 +#: apps/wei/models.py:280 msgid "team" msgstr "équipe" -#: apps/wei/models.py:289 +#: apps/wei/models.py:290 msgid "WEI registration" msgstr "inscription au WEI" -#: apps/wei/models.py:293 +#: apps/wei/models.py:294 msgid "WEI membership" msgstr "adhésion au WEI" -#: apps/wei/models.py:294 +#: apps/wei/models.py:295 msgid "WEI memberships" msgstr "adhésions au WEI" #: apps/wei/tables.py:53 apps/wei/tables.py:54 +#: templates/treasury/sogecredit_detail.html:44 msgid "Validate" msgstr "Valider" @@ -1258,7 +1280,7 @@ msgstr "Vous avez déjà ouvert un compte auprès de la société générale." msgid "This user didn't give her/his caution check." msgstr "Cet utilisateur n'a pas donné son chèque de caution." -#: apps/wei/views.py:789 apps/wei/views.py:809 apps/wei/views.py:819 +#: apps/wei/views.py:790 apps/wei/views.py:810 apps/wei/views.py:820 #: templates/wei/survey.html:12 templates/wei/survey_closed.html:12 #: templates/wei/survey_end.html:12 msgid "Survey WEI" @@ -1784,34 +1806,22 @@ msgid "Reset my password" msgstr "" #: templates/registration/signup.html:5 templates/registration/signup.html:8 -#: templates/registration/signup.html:28 +#: templates/registration/signup.html:19 msgid "Sign up" msgstr "Inscription" #: templates/registration/signup.html:11 msgid "" -"\n" -" If you already signed up, your registration is taken into " -"account. The BDE must validate your account before\n" -" your can log in. You have to go to the Kfet and pay the " -"registration fee. You must also validate your email\n" -" address by following the link you received. If you forgot to " -"register to the WEI, then you can pre-register\n" -" to the WEI after your account get validated, so please go to the " -"Kfet.\n" -" " +"If you already signed up, your registration is taken into account. The BDE " +"must validate your account before your can log in. You have to go to the " +"Kfet and pay the registration fee. You must also validate your email address " +"by following the link you received." msgstr "" -"\n" -" Si vous vous êtes déjà inscrits, votre inscription a bien été " -"prise en compte. Le BDE doit d'abord valider votre compte avant\n" -" que vous puissiez vous connecter. Vous devez vous rendre à la " -"Kfet et payer les frais d'adhésion. Vous devez également valider votre " -"adresse\n" -" email en suivant le lien que vous avez reçu. Si vous aviez " -"oublié de vous inscrire au WEI, vous pourrez vous pré-inscrire à nouveau\n" -" après avoir validé votre compte, merci alors de vous rendre à la " -"Kfet.\n" -" " +"Si vous vous êtes déjà inscrits, votre inscription a bien été prise en " +"compte. Le BDE doit d'abord valider votre compte avantque vous puissiez 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." #: templates/treasury/invoice_form.html:6 msgid "Invoices list" @@ -1825,7 +1835,13 @@ msgstr "Ajouter produit" msgid "Remove product" msgstr "Retirer produit" -#: templates/treasury/invoice_list.html:21 +#: templates/treasury/invoice_list.html:16 +#: templates/treasury/remittance_list.html:16 +#: templates/treasury/sogecredit_list.html:16 +msgid "Société générale credits" +msgstr "Crédits de la Société générale" + +#: templates/treasury/invoice_list.html:24 msgid "New invoice" msgstr "Nouvelle facture" @@ -1850,38 +1866,89 @@ msgstr "Transactions liées" msgid "There is no transaction linked with this remittance." msgstr "Il n'y a pas de transaction liée à cette remise." -#: templates/treasury/remittance_list.html:19 +#: templates/treasury/remittance_list.html:22 msgid "Opened remittances" msgstr "Remises ouvertes" -#: templates/treasury/remittance_list.html:24 +#: templates/treasury/remittance_list.html:27 msgid "There is no opened remittance." msgstr "Il n'y a pas de remise ouverte." -#: templates/treasury/remittance_list.html:28 +#: templates/treasury/remittance_list.html:31 msgid "New remittance" msgstr "Nouvelle remise" -#: templates/treasury/remittance_list.html:32 +#: templates/treasury/remittance_list.html:35 msgid "Transfers without remittances" msgstr "Transactions sans remise associée" -#: templates/treasury/remittance_list.html:37 +#: templates/treasury/remittance_list.html:40 msgid "There is no transaction without any linked remittance." msgstr "Il n'y a pas de transactions sans remise associée." -#: templates/treasury/remittance_list.html:43 +#: templates/treasury/remittance_list.html:46 msgid "Transfers with opened remittances" msgstr "Transactions associées à une remise ouverte" -#: templates/treasury/remittance_list.html:48 +#: templates/treasury/remittance_list.html:51 msgid "There is no transaction with an opened linked remittance." msgstr "Il n'y a pas de transaction associée à une remise ouverte." -#: templates/treasury/remittance_list.html:54 +#: templates/treasury/remittance_list.html:57 msgid "Closed remittances" msgstr "Remises fermées" +#: templates/treasury/sogecredit_detail.html:23 +msgid "total amount" +msgstr "montant total" + +#: templates/treasury/sogecredit_detail.html:29 +msgid "" +"Warning: Validating this credit implies that all membership transactions " +"will be validated." +msgstr "" +"Attention : Valider ce crédit implique que les transactions d'adhésion " +"seront validées." + +#: templates/treasury/sogecredit_detail.html:30 +msgid "" +"If you delete this credit, there all membership transactions will be also " +"validated, but no credit will be operated." +msgstr "" +"Si vous supprimez cette demande de crédit, alors toutes les transactions " +"d'adhésion seront aussi validées, but il n'y aura pas de transaction de " +"crédit créée." + +#: templates/treasury/sogecredit_detail.html:31 +msgid "" +"If this credit is validated, then the user won't be able to ask for a credit " +"from the Société générale." +msgstr "" +"Si ce crédit est validé, alors l'utilisateur ne pourra plus demander d'être " +"crédité par la Société générale à l'avenir." + +#: templates/treasury/sogecredit_detail.html:32 +msgid "If you think there is an error, please contact the \"respos info\"." +msgstr "Si vous pensez qu'il y a une erreur, merci de contacter un respo info." + +#: templates/treasury/sogecredit_detail.html:38 +msgid "This credit is already validated." +msgstr "Ce crédit a déjà été validé." + +#: templates/treasury/sogecredit_detail.html:49 +msgid "Return to credit list" +msgstr "Retour à la liste des crédits" + +#: templates/treasury/sogecredit_list.html:26 +msgid "Filter with unvalidated credits only" +msgstr "Filtrer avec uniquement les crédits non valides" + +#: templates/treasury/sogecredit_list.html:36 +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." + #: templates/wei/bus_tables.html:16 templates/wei/busteam_tables.html:16 msgid "Add team" msgstr "Ajouter une équipe" diff --git a/templates/member/club_info.html b/templates/member/club_info.html index 59259f10..18cfe631 100644 --- a/templates/member/club_info.html +++ b/templates/member/club_info.html @@ -19,14 +19,20 @@ {% endif %} {% if club.require_memberships %} -
{% trans 'membership start'|capfirst %}
-
{{ club.membership_start }}
+ {% if club.membership_start %} +
{% trans 'membership start'|capfirst %}
+
{{ club.membership_start }}
+ {% endif %} -
{% trans 'membership end'|capfirst %}
-
{{ club.membership_end }}
+ {% if club.membership_end %} +
{% trans 'membership end'|capfirst %}
+
{{ club.membership_end }}
+ {% endif %} -
{% trans 'membership duration'|capfirst %}
-
{{ club.membership_duration }} {% trans "days" %}
+ {% if club.membership_duration %} +
{% trans 'membership duration'|capfirst %}
+
{{ club.membership_duration }} {% trans "days" %}
+ {% endif %} {% if club.membership_fee_paid == club.membership_fee_unpaid %}
{% trans 'membership fee'|capfirst %}
@@ -52,15 +58,18 @@
{{ club.email }}
- + {% if not club.weiclub %} + + {% endif %} diff --git a/templates/registration/signup.html b/templates/registration/signup.html index d07187af..76f88a49 100644 --- a/templates/registration/signup.html +++ b/templates/registration/signup.html @@ -8,44 +8,15 @@

{% trans "Sign up" %}

- {% blocktrans %} - If you already signed up, your registration is taken into account. The BDE must validate your account before - your can log in. You have to go to the Kfet and pay the registration fee. You must also validate your email - address by following the link you received. If you forgot to register to the WEI, then you can pre-register - to the WEI after your account get validated, so please go to the Kfet. - {% endblocktrans %} + {% blocktrans %}If you already signed up, your registration is taken into account. The BDE must validate your account before your can log in. You have to go to the Kfet and pay the registration fee. You must also validate your email address by following the link you received.{% endblocktrans %}
{% csrf_token %} {{ form|crispy }} {{ profile_form|crispy }} - {{ wei_registration_form|crispy }} -
- {{ wei_form|crispy }} -
{% endblock %} - -{% block extrajavascript %} - -{% endblock %} diff --git a/templates/treasury/invoice_list.html b/templates/treasury/invoice_list.html index f14d278d..4e95816e 100644 --- a/templates/treasury/invoice_list.html +++ b/templates/treasury/invoice_list.html @@ -12,6 +12,9 @@ {% trans "Remittance" %}s + + {% trans "Société générale credits" %} + diff --git a/templates/treasury/remittance_list.html b/templates/treasury/remittance_list.html index 8bc634e4..916c47d8 100644 --- a/templates/treasury/remittance_list.html +++ b/templates/treasury/remittance_list.html @@ -12,6 +12,9 @@ {% trans "Remittance" %}s + + {% trans "Société générale credits" %} + diff --git a/templates/treasury/sogecredit_detail.html b/templates/treasury/sogecredit_detail.html new file mode 100644 index 00000000..144b829f --- /dev/null +++ b/templates/treasury/sogecredit_detail.html @@ -0,0 +1,52 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} +{% load pretty_money %} + +{% block content %} +
+
+

{% trans "Credit from the Société générale" %}

+
+
+
+
{% trans 'user'|capfirst %}
+
{{ object.user }}
+ +
{% trans 'transactions'|capfirst %}
+
+ {% for transaction in object.transactions.all %} + {{ transaction.membership.club }} ({{ transaction.amount|pretty_money }})
+ {% endfor %} +
+ +
{% trans 'total amount'|capfirst %}
+
{{ object.amount|pretty_money }}
+
+
+ +
+ {% trans 'Warning: Validating this credit implies that all membership transactions will be validated.' %} + {% trans 'If you delete this credit, there all membership transactions will be also validated, but no credit will be operated.' %} + {% trans "If this credit is validated, then the user won't be able to ask for a credit from the Société générale." %} + {% trans 'If you think there is an error, please contact the "respos info".' %} +
+ + +
+{% endblock %} diff --git a/templates/treasury/sogecredit_list.html b/templates/treasury/sogecredit_list.html new file mode 100644 index 00000000..c8a9207b --- /dev/null +++ b/templates/treasury/sogecredit_list.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} +{% load render_table from django_tables2 %} +{% load i18n %} +{% block content %} + + + + +
+ +
+
+ +
+ {% if table.data %} + {% render_table table %} + {% else %} +
+ {% trans "There is no matched user that have asked for a Société générale credit." %} +
+ {% endif %} +
+{% endblock %} + +{% block extrajavascript %} + +{% endblock %}