Raise permission denied on CreateView if you don't have the permission to create a sample instance, see #53

This commit is contained in:
Yohann D'ANELLO 2020-08-13 15:20:15 +02:00
parent 71f6436d06
commit c466715e8a
15 changed files with 584 additions and 173 deletions

View File

@ -124,7 +124,7 @@ class Activity(models.Model):
Update the activity wiki page each time the activity is updated (validation, change description, ...) Update the activity wiki page each time the activity is updated (validation, change description, ...)
""" """
ret = super().save(*args, **kwargs) ret = super().save(*args, **kwargs)
if self.pk and "scripts" in settings.INSTALLED_APPS: if settings.DEBUG and self.pk and "scripts" in settings.INSTALLED_APPS:
def refresh_activities(): def refresh_activities():
from scripts.management.commands.refresh_activities import Command as RefreshActivitiesCommand from scripts.management.commands.refresh_activities import Command as RefreshActivitiesCommand
RefreshActivitiesCommand.refresh_human_readable_wiki_page("Modification de l'activité " + self.name) RefreshActivitiesCommand.refresh_human_readable_wiki_page("Modification de l'activité " + self.name)

View File

@ -4,26 +4,39 @@
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db.models import F, Q from django.db.models import F, Q
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, TemplateView, UpdateView from django.views.generic import DetailView, TemplateView, UpdateView
from django_tables2.views import SingleTableView from django_tables2.views import SingleTableView
from note.models import Alias, NoteSpecial, NoteUser from note.models import Alias, NoteSpecial, NoteUser
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import ActivityForm, GuestForm from .forms import ActivityForm, GuestForm
from .models import Activity, Entry, Guest from .models import Activity, Entry, Guest
from .tables import ActivityTable, EntryTable, GuestTable from .tables import ActivityTable, EntryTable, GuestTable
class ActivityCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class ActivityCreateView(LoginRequiredMixin, ProtectedCreateView):
model = Activity model = Activity
form_class = ActivityForm form_class = ActivityForm
extra_context = {"title": _("Create new activity")} extra_context = {"title": _("Create new activity")}
def get_sample_object(self):
return Activity(
name="",
description="",
creater=self.request.user,
activity_type_id=1,
organizer_id=1,
attendees_club_id=1,
date_start=timezone.now(),
date_end=timezone.now(),
)
def form_valid(self, form): def form_valid(self, form):
form.instance.creater = self.request.user form.instance.creater = self.request.user
return super().form_valid(form) return super().form_valid(form)
@ -85,11 +98,20 @@ class ActivityUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]}) return reverse_lazy('activity:activity_detail', kwargs={"pk": self.kwargs["pk"]})
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
model = Guest model = Guest
form_class = GuestForm form_class = GuestForm
template_name = "activity/activity_invite.html" template_name = "activity/activity_invite.html"
def get_sample_object(self):
activity = Activity.objects.get(pk=self.kwargs["pk"])
return Guest(
activity=activity,
first_name="",
last_name="",
inviter=self.request.user.note,
)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
activity = context["form"].activity activity = context["form"].activity
@ -114,6 +136,24 @@ class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class ActivityEntryView(LoginRequiredMixin, TemplateView): class ActivityEntryView(LoginRequiredMixin, TemplateView):
template_name = "activity/activity_entry.html" template_name = "activity/activity_entry.html"
def dispatch(self, request, *args, **kwargs):
"""
Don't display the entry interface if the user has no right to see it (no right to add an entry for itself),
it is closed or doesn't manage entries.
"""
activity = Activity.objects.get(pk=self.kwargs["pk"])
sample_entry = Entry(activity=activity, note=self.request.user.note)
if not PermissionBackend.check_perm(self.request.user, "activity.add_entry", sample_entry):
raise PermissionDenied(_("You are not allowed to display the entry interface for this activity."))
if not activity.activity_type.manage_entries:
raise PermissionDenied(_("This activity does not support activity entries."))
if not activity.open:
raise PermissionDenied(_("This activity is closed."))
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)

View File

@ -1,12 +1,15 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load render_table from django_tables2 %} {% load render_table from django_tables2 %}
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<div class="row justify-content-center mb-4"> <div class="row justify-content-center mb-4">
<div class="col-md-10 text-center"> <div class="col-md-10 text-center">
<input class="form-control mx-auto w-25" type="text" id="search_field"/> <input class="form-control mx-auto w-25" type="text" id="search_field"/>
<hr> <hr>
{% if can_add_club %}
<a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}" data-turbolinks="false">{% trans "Create club" %}</a> <a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}" data-turbolinks="false">{% trans "Create club" %}</a>
{% endif %}
</div> </div>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-center">

View File

@ -3,6 +3,7 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test import TestCase from django.test import TestCase
from note.models import TransactionTemplate, TemplateCategory
""" """
Test that login page still works Test that login page still works
@ -16,6 +17,8 @@ class TemplateLoggedOutTests(TestCase):
class TemplateLoggedInTests(TestCase): class TemplateLoggedInTests(TestCase):
fixtures = ('initial', )
def setUp(self): def setUp(self):
self.user = User.objects.create_superuser( self.user = User.objects.create_superuser(
username="admin", username="admin",
@ -48,5 +51,12 @@ class TemplateLoggedInTests(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_consos_page(self): def test_consos_page(self):
# Create one button and ensure that it is visible
cat = TemplateCategory.objects.create()
TransactionTemplate.objects.create(
destination_id=5,
category=cat,
amount=0,
)
response = self.client.get('/note/consos/') response = self.client.get('/note/consos/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@ -15,7 +15,7 @@ from django.shortcuts import redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, UpdateView, TemplateView from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from django_tables2.views import SingleTableView from django_tables2.views import SingleTableView
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -26,7 +26,7 @@ from note.tables import HistoryTable, AliasTable
from note_kfet.middlewares import _set_current_user_and_ip from note_kfet.middlewares import _set_current_user_and_ip
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.models import Role from permission.models import Role
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm
from .models import Club, Membership from .models import Club, Membership
@ -295,7 +295,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
# ******************************* # # ******************************* #
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create Club Create Club
""" """
@ -304,6 +304,12 @@ class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
success_url = reverse_lazy('member:club_list') success_url = reverse_lazy('member:club_list')
extra_context = {"title": _("Create new club")} extra_context = {"title": _("Create new club")}
def get_sample_object(self):
return Club(
name="",
email="",
)
def form_valid(self, form): def form_valid(self, form):
return super().form_valid(form) return super().form_valid(form)
@ -332,6 +338,14 @@ class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
return qs return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["can_add_club"] = PermissionBackend.check_perm(self.request.user, "member.add_club", Club(
name="",
email="club@example.com",
))
return context
class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
""" """
@ -432,7 +446,7 @@ class ClubPictureUpdateView(PictureUpdateView):
return reverse_lazy('member:club_detail', kwargs={'pk': self.object.id}) return reverse_lazy('member:club_detail', kwargs={'pk': self.object.id})
class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Add a membership to a club. Add a membership to a club.
""" """
@ -441,6 +455,19 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
template_name = 'member/add_members.html' template_name = 'member/add_members.html'
extra_context = {"title": _("Add new member to the club")} extra_context = {"title": _("Add new member to the club")}
def get_sample_object(self):
if "club_pk" in self.kwargs:
club = Club.objects.get(pk=self.kwargs["club_pk"])
else:
club = Membership.objects.get(pk=self.kwargs["pk"]).club
return Membership(
user=self.request.user,
club=club,
fee=0,
date_start=timezone.now(),
date_end=timezone.now() + timedelta(days=1),
)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
form = context['form'] form = context['form']

View File

@ -1,10 +1,12 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import json import json
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db.models import Q, F from django.db.models import Q, F
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView, DetailView from django.views.generic import CreateView, UpdateView, DetailView
@ -145,6 +147,14 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
# Transaction history table # Transaction history table
table_class = HistoryTable table_class = HistoryTable
def dispatch(self, request, *args, **kwargs):
templates = TransactionTemplate.objects.filter(
PermissionBackend().filter_queryset(self.request.user, TransactionTemplate, "view")
)
if not templates.exists():
raise PermissionDenied(_("You can't see any button."))
return super().dispatch(request, *args, **kwargs)
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
return Transaction.objects.filter( return Transaction.objects.filter(
PermissionBackend.filter_queryset(self.request.user, Transaction, "view") PermissionBackend.filter_queryset(self.request.user, Transaction, "view")

View File

@ -70,7 +70,7 @@ def pre_save_object(sender, instance, **kwargs):
if not has_perm: if not has_perm:
raise PermissionDenied( raise PermissionDenied(
_("You don't have the permission to add this instance of model {app_label}.{model_name}.") _("You don't have the permission to add an instance of model {app_label}.{model_name}.")
.format(app_label=app_label, model_name=model_name, )) .format(app_label=app_label, model_name=model_name, ))

View File

View File

@ -0,0 +1,150 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from datetime import timedelta
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from activity.models import Activity
from member.models import Club, Membership
from note.models import NoteUser
from wei.models import WEIClub, Bus, WEIRegistration
class TestPermissionDenied(TestCase):
"""
Load some protected pages and check that we have 403 errors.
"""
fixtures = ('initial',)
def setUp(self) -> None:
# Create sample user with no rights
self.user = User.objects.create(
username="toto",
)
NoteUser.objects.create(user=self.user)
self.client.force_login(self.user)
def test_consos(self):
response = self.client.get(reverse("note:consos"))
self.assertEqual(response.status_code, 403)
def test_create_activity(self):
response = self.client.get(reverse("activity:activity_create"))
self.assertEqual(response.status_code, 403)
def test_activity_entries(self):
activity = Activity.objects.create(
name="",
description="",
creater=self.user,
activity_type_id=1,
organizer_id=1,
attendees_club_id=1,
date_start=timezone.now(),
date_end=timezone.now(),
)
response = self.client.get(reverse("activity:activity_entry", kwargs=dict(pk=activity.pk)))
self.assertEqual(response.status_code, 403)
def test_invite_activity(self):
activity = Activity.objects.create(
name="",
description="",
creater=self.user,
activity_type_id=1,
organizer_id=1,
attendees_club_id=1,
date_start=timezone.now(),
date_end=timezone.now(),
)
response = self.client.get(reverse("activity:activity_invite", kwargs=dict(pk=activity.pk)))
self.assertEqual(response.status_code, 403)
def test_create_club(self):
response = self.client.get(reverse("member:club_create"))
self.assertEqual(response.status_code, 403)
def test_add_member_club(self):
club = Club.objects.create()
response = self.client.get(reverse("member:club_add_member", kwargs=dict(club_pk=club.pk)))
self.assertEqual(response.status_code, 403)
def test_renew_membership(self):
club = Club.objects.create()
membership = Membership.objects.create(user=self.user, club=club)
response = self.client.get(reverse("member:club_renew_membership", kwargs=dict(pk=membership.pk)))
self.assertEqual(response.status_code, 403)
def test_create_weiclub(self):
response = self.client.get(reverse("wei:wei_create"))
self.assertEqual(response.status_code, 403)
def test_create_wei_bus(self):
wei = WEIClub.objects.create(
membership_start=timezone.now().date(),
date_start=timezone.now().date() + timedelta(days=1),
date_end=timezone.now().date() + timedelta(days=1),
)
response = self.client.get(reverse("wei:add_bus", kwargs=dict(pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_create_wei_team(self):
wei = WEIClub.objects.create(
membership_start=timezone.now().date(),
date_start=timezone.now().date() + timedelta(days=1),
date_end=timezone.now().date() + timedelta(days=1),
)
bus = Bus.objects.create(wei=wei)
response = self.client.get(reverse("wei:add_team", kwargs=dict(pk=bus.pk)))
self.assertEqual(response.status_code, 403)
def test_create_1a_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=timezone.now().date(),
date_start=timezone.now().date() + timedelta(days=1),
date_end=timezone.now().date() + timedelta(days=1),
)
response = self.client.get(reverse("wei:wei_register_1A", kwargs=dict(wei_pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_create_old_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=timezone.now().date(),
date_start=timezone.now().date() + timedelta(days=1),
date_end=timezone.now().date() + timedelta(days=1),
)
response = self.client.get(reverse("wei:wei_register_2A", kwargs=dict(wei_pk=wei.pk)))
self.assertEqual(response.status_code, 403)
def test_validate_weiregistration(self):
wei = WEIClub.objects.create(
membership_start=timezone.now().date(),
date_start=timezone.now().date() + timedelta(days=1),
date_end=timezone.now().date() + timedelta(days=1),
)
registration = WEIRegistration.objects.create(wei=wei, user=self.user, birth_date="2000-01-01")
response = self.client.get(reverse("wei:validate_registration", kwargs=dict(pk=registration.pk)))
self.assertEqual(response.status_code, 403)
def test_create_invoice(self):
response = self.client.get(reverse("treasury:invoice_create"))
self.assertEqual(response.status_code, 403)
def test_list_invoices(self):
response = self.client.get(reverse("treasury:invoice_list"))
self.assertEqual(response.status_code, 403)
def test_create_remittance(self):
response = self.client.get(reverse("treasury:remittance_create"))
self.assertEqual(response.status_code, 403)
def test_list_remittance(self):
response = self.client.get(reverse("treasury:remittance_list"))
self.assertEqual(response.status_code, 403)
def test_list_soge_credits(self):
response = self.client.get(reverse("treasury:soge_credits"))
self.assertEqual(response.status_code, 403)

View File

@ -10,7 +10,7 @@ from member.models import Club, Membership
from note.models import NoteUser, Note, NoteClub, NoteSpecial from note.models import NoteUser, Note, NoteClub, NoteSpecial
from wei.models import WEIMembership, WEIRegistration, WEIClub, Bus, BusTeam from wei.models import WEIMembership, WEIRegistration, WEIClub, Bus, BusTeam
from .models import Permission from ..models import Permission
class PermissionQueryTestCase(TestCase): class PermissionQueryTestCase(TestCase):

View File

@ -1,12 +1,14 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date from datetime import date
from django.core.exceptions import PermissionDenied
from django.db.models import Q from django.db.models import Q
from django.forms import HiddenInput from django.forms import HiddenInput
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView, TemplateView from django.views.generic import UpdateView, TemplateView, CreateView
from member.models import Membership from member.models import Membership
from .backends import PermissionBackend from .backends import PermissionBackend
@ -42,6 +44,30 @@ class ProtectQuerysetMixin:
return form return form
class ProtectedCreateView(CreateView):
"""
Extends a CreateView to check is the user has the right to create a sample instance of the given Model.
If not, a 403 error is displayed.
"""
def get_sample_object(self):
"""
return a sample instance of the Model.
It should be valid (can be stored properly in database), but must not collide with existing data.
"""
raise NotImplementedError
def dispatch(self, request, *args, **kwargs):
model_class = self.model
# noinspection PyProtectedMember
app_label, model_name = model_class._meta.app_label, model_class._meta.model_name.lower()
perm = app_label + ".add_" + model_name
if not PermissionBackend.check_perm(request.user, perm, self.get_sample_object()):
raise PermissionDenied(_("You don't have the permission to add an instance of model "
"{app_label}.{model_name}.").format(app_label=app_label, model_name=model_name))
return super().dispatch(request, *args, **kwargs)
class RightsView(TemplateView): class RightsView(TemplateView):
template_name = "permission/all_rights.html" template_name = "permission/all_rights.html"
extra_context = {"title": _("Rights")} extra_context = {"title": _("Rights")}

View File

@ -8,28 +8,28 @@ from tempfile import mkdtemp
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError, PermissionDenied
from django.db.models import Q from django.db.models import Q
from django.forms import Form from django.forms import Form
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView, DetailView from django.views.generic import UpdateView, DetailView
from django.views.generic.base import View, TemplateView from django.views.generic.base import View, TemplateView
from django.views.generic.edit import BaseFormView, DeleteView from django.views.generic.edit import BaseFormView, DeleteView
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from note.models import SpecialTransaction, NoteSpecial, Alias from note.models import SpecialTransaction, NoteSpecial, Alias
from note_kfet.settings.base import BASE_DIR from note_kfet.settings.base import BASE_DIR
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create Invoice Create Invoice
""" """
@ -37,6 +37,15 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = InvoiceForm form_class = InvoiceForm
extra_context = {"title": _("Create new invoice")} extra_context = {"title": _("Create new invoice")}
def get_sample_object(self):
return Invoice(
id=0,
object="",
description="",
name="",
address="",
)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -72,7 +81,7 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
return reverse_lazy('treasury:invoice_list') return reverse_lazy('treasury:invoice_list')
class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): class InvoiceListView(LoginRequiredMixin, SingleTableView):
""" """
List existing Invoices List existing Invoices
""" """
@ -80,6 +89,18 @@ class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView)
table_class = InvoiceTable table_class = InvoiceTable
extra_context = {"title": _("Invoices list")} extra_context = {"title": _("Invoices list")}
def dispatch(self, request, *args, **kwargs):
sample_invoice = Invoice(
id=0,
object="",
description="",
name="",
address="",
)
if not PermissionBackend.check_perm(self.request.user, "treasury.add_invoice", sample_invoice):
raise PermissionDenied(_("You are not able to see the treasury interface."))
return super().dispatch(request, *args, **kwargs)
class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
""" """
@ -194,7 +215,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
return response return response
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create Remittance Create Remittance
""" """
@ -202,6 +223,12 @@ class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView)
form_class = RemittanceForm form_class = RemittanceForm
extra_context = {"title": _("Create a new remittance")} extra_context = {"title": _("Create a new remittance")}
def get_sample_object(self):
return Remittance(
remittance_type_id=1,
comment="",
)
def get_success_url(self): def get_success_url(self):
return reverse_lazy('treasury:remittance_list') return reverse_lazy('treasury:remittance_list')
@ -223,6 +250,15 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
template_name = "treasury/remittance_list.html" template_name = "treasury/remittance_list.html"
extra_context = {"title": _("Remittances list")} extra_context = {"title": _("Remittances list")}
def dispatch(self, request, *args, **kwargs):
sample_remittance = Remittance(
remittance_type_id=1,
comment="",
)
if not PermissionBackend.check_perm(self.request.user, "treasury.add_remittance", sample_remittance):
raise PermissionDenied(_("You are not able to see the treasury interface."))
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -340,6 +376,11 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
table_class = SogeCreditTable table_class = SogeCreditTable
extra_context = {"title": _("List of credits from the Société générale")} extra_context = {"title": _("List of credits from the Société générale")}
def dispatch(self, request, *args, **kwargs):
if not self.get_queryset().exists():
raise PermissionDenied(_("You are not able to see the treasury interface."))
return super().dispatch(request, *args, **kwargs)
def get_queryset(self, **kwargs): def get_queryset(self, **kwargs):
""" """
Filter the table with the given parameter. Filter the table with the given parameter.

View File

@ -4,7 +4,7 @@
import os import os
import shutil import shutil
import subprocess import subprocess
from datetime import datetime, date from datetime import datetime, date, timedelta
from tempfile import mkdtemp from tempfile import mkdtemp
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
@ -19,7 +19,7 @@ from django.template.loader import render_to_string
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.views import View from django.views import View
from django.views.generic import DetailView, UpdateView, CreateView, RedirectView, TemplateView from django.views.generic import DetailView, UpdateView, RedirectView, TemplateView
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import BaseFormView, DeleteView from django.views.generic.edit import BaseFormView, DeleteView
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
@ -28,7 +28,7 @@ from note.models import Transaction, NoteClub, Alias, SpecialTransaction, NoteSp
from note.tables import HistoryTable from note.tables import HistoryTable
from note_kfet.settings import BASE_DIR from note_kfet.settings import BASE_DIR
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms.registration import WEIChooseBusForm from .forms.registration import WEIChooseBusForm
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
@ -58,6 +58,8 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["can_create_wei"] = PermissionBackend.check_perm(self.request.user, "wei.add_weiclub", WEIClub( context["can_create_wei"] = PermissionBackend.check_perm(self.request.user, "wei.add_weiclub", WEIClub(
name="",
email="weiclub@example.com",
year=0, year=0,
date_start=timezone.now().date(), date_start=timezone.now().date(),
date_end=timezone.now().date(), date_end=timezone.now().date(),
@ -65,14 +67,24 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
return context return context
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create WEI Create WEI
""" """
model = WEIClub model = WEIClub
form_class = WEIForm form_class = WEIForm
extra_context = {"title": _("Create WEI")} extra_context = {"title": _("Create WEI")}
def get_sample_object(self):
return WEIClub(
name="",
email="weiclub@example.com",
year=0,
date_start=timezone.now().date(),
date_end=timezone.now().date(),
)
def form_valid(self, form): def form_valid(self, form):
form.instance.requires_membership = True form.instance.requires_membership = True
form.instance.parent_club = Club.objects.get(name="Kfet") form.instance.parent_club = Club.objects.get(name="Kfet")
@ -274,7 +286,7 @@ class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk}) return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk})
class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create Bus Create Bus
""" """
@ -282,6 +294,13 @@ class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = BusForm form_class = BusForm
extra_context = {"title": _("Create new bus")} extra_context = {"title": _("Create new bus")}
def get_sample_object(self):
wei = WEIClub.objects.get(pk=self.kwargs["pk"])
return Bus(
wei=wei,
name="",
)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["pk"]) wei = WEIClub.objects.get(pk=self.kwargs["pk"])
today = date.today() today = date.today()
@ -362,7 +381,7 @@ class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
return context return context
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Create BusTeam Create BusTeam
""" """
@ -370,6 +389,14 @@ class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = BusTeamForm form_class = BusTeamForm
extra_context = {"title": _("Create new team")} extra_context = {"title": _("Create new team")}
def get_sample_object(self):
bus = Bus.objects.get(pk=self.kwargs["pk"])
return BusTeam(
name="",
bus=bus,
color=0,
)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"]) wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"])
today = date.today() today = date.today()
@ -447,7 +474,7 @@ class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
return context return context
class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Register a new user to the WEI Register a new user to the WEI
""" """
@ -455,6 +482,18 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = WEIRegistrationForm form_class = WEIRegistrationForm
extra_context = {"title": _("Register first year student to the WEI")} extra_context = {"title": _("Register first year student to the WEI")}
def get_sample_object(self):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
return WEIRegistration(
wei=wei,
user=self.request.user,
first_year=True,
birth_date="1970-01-01",
gender="No",
emergency_contact_name="No",
emergency_contact_phone="No",
)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
today = date.today() today = date.today()
@ -502,7 +541,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk}) return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Register an old user to the WEI Register an old user to the WEI
""" """
@ -510,6 +549,18 @@ class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = WEIRegistrationForm form_class = WEIRegistrationForm
extra_context = {"title": _("Register old student to the WEI")} extra_context = {"title": _("Register old student to the WEI")}
def get_sample_object(self):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
return WEIRegistration(
wei=wei,
user=self.request.user,
first_year=True,
birth_date="1970-01-01",
gender="No",
emergency_contact_name="No",
emergency_contact_phone="No",
)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
today = date.today() today = date.today()
@ -713,7 +764,7 @@ class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Delete
return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,)) return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,))
class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
""" """
Validate WEI Registration Validate WEI Registration
""" """
@ -721,6 +772,17 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
form_class = WEIMembershipForm form_class = WEIMembershipForm
extra_context = {"title": _("Validate WEI registration")} extra_context = {"title": _("Validate WEI registration")}
def get_sample_object(self):
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
return WEIMembership(
club=registration.wei,
user=registration.user,
date_start=timezone.now().date(),
date_end=timezone.now().date() + timedelta(days=1),
fee=0,
registration=registration,
)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
today = date.today() today = date.today()

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-10 19:56+0200\n" "POT-Creation-Date: 2020-08-13 15:15+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -327,27 +327,39 @@ msgstr ""
msgid "All activities" msgid "All activities"
msgstr "" msgstr ""
#: apps/activity/views.py:25 #: apps/activity/views.py:26
msgid "Create new activity" msgid "Create new activity"
msgstr "" msgstr ""
#: apps/activity/views.py:40 note_kfet/templates/base.html:128 #: apps/activity/views.py:53 note_kfet/templates/base.html:128
msgid "Activities" msgid "Activities"
msgstr "" msgstr ""
#: apps/activity/views.py:65 #: apps/activity/views.py:78
msgid "Activity detail" msgid "Activity detail"
msgstr "" msgstr ""
#: apps/activity/views.py:82 #: apps/activity/views.py:95
msgid "Update activity" msgid "Update activity"
msgstr "" msgstr ""
#: apps/activity/views.py:96 #: apps/activity/views.py:118
msgid "Invite guest to the activity \"{}\"" msgid "Invite guest to the activity \"{}\""
msgstr "" msgstr ""
#: apps/activity/views.py:197 #: apps/activity/views.py:148
msgid "You are not allowed to display the entry interface for this activity."
msgstr ""
#: apps/activity/views.py:151
msgid "This activity does not support activity entries."
msgstr ""
#: apps/activity/views.py:154
msgid "This activity is closed."
msgstr ""
#: apps/activity/views.py:237
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "" msgstr ""
@ -682,7 +694,7 @@ msgstr ""
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "" msgstr ""
#: apps/member/models.py:362 apps/member/views.py:592 #: apps/member/models.py:362 apps/member/views.py:619
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "" msgstr ""
@ -774,11 +786,11 @@ msgstr ""
msgid "View Profile" msgid "View Profile"
msgstr "" msgstr ""
#: apps/member/templates/member/club_list.html:9 #: apps/member/templates/member/club_list.html:11
msgid "Create club" msgid "Create club"
msgstr "" msgstr ""
#: apps/member/templates/member/club_list.html:16 #: apps/member/templates/member/club_list.html:19
msgid "Club listing" msgid "Club listing"
msgstr "" msgstr ""
@ -890,7 +902,7 @@ msgstr ""
msgid "Search user" msgid "Search user"
msgstr "" msgstr ""
#: apps/member/views.py:205 apps/member/views.py:391 #: apps/member/views.py:205 apps/member/views.py:405
msgid "Note aliases" msgid "Note aliases"
msgstr "" msgstr ""
@ -902,47 +914,47 @@ msgstr ""
msgid "Create new club" msgid "Create new club"
msgstr "" msgstr ""
#: apps/member/views.py:317 #: apps/member/views.py:323
msgid "Search club" msgid "Search club"
msgstr "" msgstr ""
#: apps/member/views.py:342 #: apps/member/views.py:356
msgid "Club detail" msgid "Club detail"
msgstr "" msgstr ""
#: apps/member/views.py:408 #: apps/member/views.py:422
msgid "Update club" msgid "Update club"
msgstr "" msgstr ""
#: apps/member/views.py:442 #: apps/member/views.py:456
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "" msgstr ""
#: apps/member/views.py:583 apps/wei/views.py:861 #: apps/member/views.py:610 apps/wei/views.py:926
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
msgstr "" msgstr ""
#: apps/member/views.py:596 #: apps/member/views.py:623
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:601 #: apps/member/views.py:628
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "" msgstr ""
#: apps/member/views.py:618 apps/member/views.py:620 apps/member/views.py:622 #: apps/member/views.py:645 apps/member/views.py:647 apps/member/views.py:649
#: apps/registration/views.py:292 apps/registration/views.py:294 #: apps/registration/views.py:292 apps/registration/views.py:294
#: apps/registration/views.py:296 apps/wei/views.py:866 apps/wei/views.py:870 #: apps/registration/views.py:296 apps/wei/views.py:931 apps/wei/views.py:935
msgid "This field is required." msgid "This field is required."
msgstr "" msgstr ""
#: apps/member/views.py:706 #: apps/member/views.py:733
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "" msgstr ""
#: apps/member/views.py:731 #: apps/member/views.py:758
msgid "Members of the club" msgid "Members of the club"
msgstr "" msgstr ""
@ -1223,7 +1235,7 @@ msgstr ""
#: apps/note/tables.py:138 apps/note/tables.py:172 apps/treasury/tables.py:39 #: apps/note/tables.py:138 apps/note/tables.py:172 apps/treasury/tables.py:39
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:28 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:28
#: apps/treasury/templates/treasury/sogecredit_detail.html:59 #: apps/treasury/templates/treasury/sogecredit_detail.html:59
#: apps/wei/tables.py:75 apps/wei/tables.py:101 #: apps/wei/tables.py:75 apps/wei/tables.py:102
#: apps/wei/templates/wei/weiregistration_confirm_delete.html:32 #: apps/wei/templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
@ -1340,27 +1352,31 @@ msgstr ""
msgid "Unable to delete button " msgid "Unable to delete button "
msgstr "" msgstr ""
#: apps/note/views.py:34 #: apps/note/views.py:36
msgid "Transfer money" msgid "Transfer money"
msgstr "" msgstr ""
#: apps/note/views.py:74 #: apps/note/views.py:76
msgid "Create new button" msgid "Create new button"
msgstr "" msgstr ""
#: apps/note/views.py:83 #: apps/note/views.py:85
msgid "Search button" msgid "Search button"
msgstr "" msgstr ""
#: apps/note/views.py:106 #: apps/note/views.py:108
msgid "Update button" msgid "Update button"
msgstr "" msgstr ""
#: apps/note/views.py:143 note_kfet/templates/base.html:108 #: apps/note/views.py:145 note_kfet/templates/base.html:108
msgid "Consumptions" msgid "Consumptions"
msgstr "" msgstr ""
#: apps/note/views.py:179 #: apps/note/views.py:155
msgid "You can't see any button."
msgstr ""
#: apps/note/views.py:189
msgid "Search transactions" msgid "Search transactions"
msgstr "" msgstr ""
@ -1448,10 +1464,10 @@ msgid ""
"of model {app_label}.{model_name}." "of model {app_label}.{model_name}."
msgstr "" msgstr ""
#: apps/permission/signals.py:73 #: apps/permission/signals.py:73 apps/permission/views.py:66
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"You don't have the permission to add this instance of model {app_label}." "You don't have the permission to add an instance of model {app_label}."
"{model_name}." "{model_name}."
msgstr "" msgstr ""
@ -1490,11 +1506,11 @@ msgstr ""
msgid "No associated permission" msgid "No associated permission"
msgstr "" msgstr ""
#: apps/permission/views.py:47 note_kfet/templates/base.html:143 #: apps/permission/views.py:73 note_kfet/templates/base.html:143
msgid "Rights" msgid "Rights"
msgstr "" msgstr ""
#: apps/permission/views.py:52 #: apps/permission/views.py:78
msgid "All rights" msgid "All rights"
msgstr "" msgstr ""
@ -1864,7 +1880,7 @@ msgid "No"
msgstr "" msgstr ""
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:8 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:8
#: apps/treasury/views.py:143 #: apps/treasury/views.py:164
msgid "Delete invoice" msgid "Delete invoice"
msgstr "" msgstr ""
@ -1882,7 +1898,7 @@ msgid "Return to invoices list"
msgstr "" msgstr ""
#: apps/treasury/templates/treasury/invoice_form.html:6 #: apps/treasury/templates/treasury/invoice_form.html:6
#: apps/treasury/views.py:81 #: apps/treasury/views.py:90
msgid "Invoices list" msgid "Invoices list"
msgstr "" msgstr ""
@ -1916,7 +1932,7 @@ msgstr ""
#: apps/treasury/templates/treasury/remittance_form.html:9 #: apps/treasury/templates/treasury/remittance_form.html:9
#: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7 #: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7
#: apps/treasury/views.py:224 #: apps/treasury/views.py:251
msgid "Remittances list" msgid "Remittances list"
msgstr "" msgstr ""
@ -2009,7 +2025,7 @@ msgid "Please ask the user to credit its note before deleting this credit."
msgstr "" msgstr ""
#: apps/treasury/templates/treasury/sogecredit_detail.html:57 #: apps/treasury/templates/treasury/sogecredit_detail.html:57
#: apps/wei/tables.py:58 apps/wei/tables.py:59 apps/wei/tables.py:96 #: apps/wei/tables.py:58 apps/wei/tables.py:59 apps/wei/tables.py:98
msgid "Validate" msgid "Validate"
msgstr "" msgstr ""
@ -2029,27 +2045,32 @@ msgstr ""
msgid "Create new invoice" msgid "Create new invoice"
msgstr "" msgstr ""
#: apps/treasury/views.py:90 #: apps/treasury/views.py:101 apps/treasury/views.py:259
#: apps/treasury/views.py:381
msgid "You are not able to see the treasury interface."
msgstr ""
#: apps/treasury/views.py:111
msgid "Update an invoice" msgid "Update an invoice"
msgstr "" msgstr ""
#: apps/treasury/views.py:203 #: apps/treasury/views.py:224
msgid "Create a new remittance" msgid "Create a new remittance"
msgstr "" msgstr ""
#: apps/treasury/views.py:274 #: apps/treasury/views.py:310
msgid "Update a remittance" msgid "Update a remittance"
msgstr "" msgstr ""
#: apps/treasury/views.py:297 #: apps/treasury/views.py:333
msgid "Attach a transaction to a remittance" msgid "Attach a transaction to a remittance"
msgstr "" msgstr ""
#: apps/treasury/views.py:341 #: apps/treasury/views.py:377
msgid "List of credits from the Société générale" msgid "List of credits from the Société générale"
msgstr "" msgstr ""
#: apps/treasury/views.py:375 #: apps/treasury/views.py:416
msgid "Manage credits from the Société générale" msgid "Manage credits from the Société générale"
msgstr "" msgstr ""
@ -2287,8 +2308,8 @@ msgstr ""
#: apps/wei/templates/wei/survey.html:12 #: apps/wei/templates/wei/survey.html:12
#: apps/wei/templates/wei/survey_closed.html:12 #: apps/wei/templates/wei/survey_closed.html:12
#: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:917 #: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:982
#: apps/wei/views.py:971 apps/wei/views.py:981 #: apps/wei/views.py:1036 apps/wei/views.py:1046
msgid "Survey WEI" msgid "Survey WEI"
msgstr "" msgstr ""
@ -2320,11 +2341,11 @@ msgstr ""
msgid "WEI list" msgid "WEI list"
msgstr "" msgstr ""
#: apps/wei/templates/wei/weiclub_info.html:62 apps/wei/views.py:468 #: apps/wei/templates/wei/weiclub_info.html:62 apps/wei/views.py:507
msgid "Register 1A" msgid "Register 1A"
msgstr "" msgstr ""
#: apps/wei/templates/wei/weiclub_info.html:65 apps/wei/views.py:523 #: apps/wei/templates/wei/weiclub_info.html:65 apps/wei/views.py:574
msgid "Register 2A+" msgid "Register 2A+"
msgstr "" msgstr ""
@ -2336,7 +2357,7 @@ msgstr ""
msgid "View WEI" msgid "View WEI"
msgstr "" msgstr ""
#: apps/wei/templates/wei/weiclub_list.html:10 apps/wei/views.py:74 #: apps/wei/templates/wei/weiclub_list.html:10 apps/wei/views.py:77
msgid "Create WEI" msgid "Create WEI"
msgstr "" msgstr ""
@ -2489,93 +2510,93 @@ msgstr ""
msgid "Search WEI" msgid "Search WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:94 #: apps/wei/views.py:106
msgid "WEI Detail" msgid "WEI Detail"
msgstr "" msgstr ""
#: apps/wei/views.py:189 #: apps/wei/views.py:201
msgid "View members of the WEI" msgid "View members of the WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:217 #: apps/wei/views.py:229
msgid "Find WEI Membership" msgid "Find WEI Membership"
msgstr "" msgstr ""
#: apps/wei/views.py:227 #: apps/wei/views.py:239
msgid "View registrations to the WEI" msgid "View registrations to the WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:251 #: apps/wei/views.py:263
msgid "Find WEI Registration" msgid "Find WEI Registration"
msgstr "" msgstr ""
#: apps/wei/views.py:262 #: apps/wei/views.py:274
msgid "Update the WEI" msgid "Update the WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:283 #: apps/wei/views.py:295
msgid "Create new bus" msgid "Create new bus"
msgstr "" msgstr ""
#: apps/wei/views.py:314 #: apps/wei/views.py:333
msgid "Update bus" msgid "Update bus"
msgstr "" msgstr ""
#: apps/wei/views.py:344 #: apps/wei/views.py:363
msgid "Manage bus" msgid "Manage bus"
msgstr "" msgstr ""
#: apps/wei/views.py:371 #: apps/wei/views.py:390
msgid "Create new team" msgid "Create new team"
msgstr "" msgstr ""
#: apps/wei/views.py:403 #: apps/wei/views.py:430
msgid "Update team" msgid "Update team"
msgstr "" msgstr ""
#: apps/wei/views.py:434 #: apps/wei/views.py:461
msgid "Manage WEI team" msgid "Manage WEI team"
msgstr "" msgstr ""
#: apps/wei/views.py:456 #: apps/wei/views.py:483
msgid "Register first year student to the WEI" msgid "Register first year student to the WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:489 apps/wei/views.py:560 #: apps/wei/views.py:528 apps/wei/views.py:611
msgid "This user is already registered to this WEI." msgid "This user is already registered to this WEI."
msgstr "" msgstr ""
#: apps/wei/views.py:494 #: apps/wei/views.py:533
msgid "" msgid ""
"This user can't be in her/his first year since he/she has already participated " "This user can't be in her/his first year since he/she has already "
"to a WEI." "participated to a WEI."
msgstr "" msgstr ""
#: apps/wei/views.py:511 #: apps/wei/views.py:550
msgid "Register old student to the WEI" msgid "Register old student to the WEI"
msgstr "" msgstr ""
#: apps/wei/views.py:542 apps/wei/views.py:627 #: apps/wei/views.py:593 apps/wei/views.py:684
msgid "You already opened an account in the Société générale." msgid "You already opened an account in the Société générale."
msgstr "" msgstr ""
#: apps/wei/views.py:590 #: apps/wei/views.py:641
msgid "Update WEI Registration" msgid "Update WEI Registration"
msgstr "" msgstr ""
#: apps/wei/views.py:686 #: apps/wei/views.py:743
msgid "Delete WEI registration" msgid "Delete WEI registration"
msgstr "" msgstr ""
#: apps/wei/views.py:697 #: apps/wei/views.py:754
msgid "You don't have the right to delete this WEI registration." msgid "You don't have the right to delete this WEI registration."
msgstr "" msgstr ""
#: apps/wei/views.py:716 #: apps/wei/views.py:773
msgid "Validate WEI registration" msgid "Validate WEI registration"
msgstr "" msgstr ""
#: apps/wei/views.py:855 #: apps/wei/views.py:920
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-10 19:56+0200\n" "POT-Creation-Date: 2020-08-13 15:15+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -328,27 +328,39 @@ msgstr "Nouvelle activité"
msgid "All activities" msgid "All activities"
msgstr "Toutes les activités" msgstr "Toutes les activités"
#: apps/activity/views.py:25 #: apps/activity/views.py:26
msgid "Create new activity" msgid "Create new activity"
msgstr "Créer une nouvelle activité" msgstr "Créer une nouvelle activité"
#: apps/activity/views.py:40 note_kfet/templates/base.html:128 #: apps/activity/views.py:53 note_kfet/templates/base.html:128
msgid "Activities" msgid "Activities"
msgstr "Activités" msgstr "Activités"
#: apps/activity/views.py:65 #: apps/activity/views.py:78
msgid "Activity detail" msgid "Activity detail"
msgstr "Détails de l'activité" msgstr "Détails de l'activité"
#: apps/activity/views.py:82 #: apps/activity/views.py:95
msgid "Update activity" msgid "Update activity"
msgstr "Modifier l'activité" msgstr "Modifier l'activité"
#: apps/activity/views.py:96 #: apps/activity/views.py:118
msgid "Invite guest to the activity \"{}\"" msgid "Invite guest to the activity \"{}\""
msgstr "Invitation pour l'activité « {} »" msgstr "Invitation pour l'activité « {} »"
#: apps/activity/views.py:197 #: apps/activity/views.py:148
msgid "You are not allowed to display the entry interface for this activity."
msgstr "Vous n'êtes pas autorisé à afficher l'interface des entrées pour cette activité."
#: apps/activity/views.py:151
msgid "This activity does not support activity entries."
msgstr "Cette activité ne requiert pas d'entrées."
#: apps/activity/views.py:154
msgid "This activity is closed."
msgstr "Cette activité est fermée."
#: apps/activity/views.py:237
msgid "Entry for activity \"{}\"" msgid "Entry for activity \"{}\""
msgstr "Entrées pour l'activité « {} »" msgstr "Entrées pour l'activité « {} »"
@ -686,7 +698,7 @@ msgstr "l'adhésion finit le"
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}." msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:362 apps/member/views.py:592 #: apps/member/models.py:362 apps/member/views.py:619
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club" msgstr "L'utilisateur est déjà membre du club"
@ -783,11 +795,11 @@ msgstr "Éditer"
msgid "View Profile" msgid "View Profile"
msgstr "Voir le profil" msgstr "Voir le profil"
#: apps/member/templates/member/club_list.html:9 #: apps/member/templates/member/club_list.html:11
msgid "Create club" msgid "Create club"
msgstr "Créer un club" msgstr "Créer un club"
#: apps/member/templates/member/club_list.html:16 #: apps/member/templates/member/club_list.html:19
msgid "Club listing" msgid "Club listing"
msgstr "Liste des clubs" msgstr "Liste des clubs"
@ -899,7 +911,7 @@ msgstr "Détails de l'utilisateur"
msgid "Search user" msgid "Search user"
msgstr "Chercher un utilisateur" msgstr "Chercher un utilisateur"
#: apps/member/views.py:205 apps/member/views.py:391 #: apps/member/views.py:205 apps/member/views.py:405
msgid "Note aliases" msgid "Note aliases"
msgstr "Alias de la note" msgstr "Alias de la note"
@ -911,23 +923,23 @@ msgstr "Modifier la photo de la note"
msgid "Create new club" msgid "Create new club"
msgstr "Créer un nouveau club" msgstr "Créer un nouveau club"
#: apps/member/views.py:317 #: apps/member/views.py:323
msgid "Search club" msgid "Search club"
msgstr "Chercher un club" msgstr "Chercher un club"
#: apps/member/views.py:342 #: apps/member/views.py:356
msgid "Club detail" msgid "Club detail"
msgstr "Détails du club" msgstr "Détails du club"
#: apps/member/views.py:408 #: apps/member/views.py:422
msgid "Update club" msgid "Update club"
msgstr "Modifier le club" msgstr "Modifier le club"
#: apps/member/views.py:442 #: apps/member/views.py:456
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club" msgstr "Ajouter un nouveau membre au club"
#: apps/member/views.py:583 apps/wei/views.py:861 #: apps/member/views.py:610 apps/wei/views.py:926
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
@ -935,25 +947,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas " "Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif." "avoir un solde négatif."
#: apps/member/views.py:596 #: apps/member/views.py:623
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
#: apps/member/views.py:601 #: apps/member/views.py:628
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:618 apps/member/views.py:620 apps/member/views.py:622 #: apps/member/views.py:645 apps/member/views.py:647 apps/member/views.py:649
#: apps/registration/views.py:292 apps/registration/views.py:294 #: apps/registration/views.py:292 apps/registration/views.py:294
#: apps/registration/views.py:296 apps/wei/views.py:866 apps/wei/views.py:870 #: apps/registration/views.py:296 apps/wei/views.py:931 apps/wei/views.py:935
msgid "This field is required." msgid "This field is required."
msgstr "Ce champ est requis." msgstr "Ce champ est requis."
#: apps/member/views.py:706 #: apps/member/views.py:733
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club" msgstr "Gérer les rôles d'un utilisateur dans le club"
#: apps/member/views.py:731 #: apps/member/views.py:758
msgid "Members of the club" msgid "Members of the club"
msgstr "Membres du club" msgstr "Membres du club"
@ -1241,7 +1253,7 @@ msgstr "Pas de motif spécifié"
#: apps/note/tables.py:138 apps/note/tables.py:172 apps/treasury/tables.py:39 #: apps/note/tables.py:138 apps/note/tables.py:172 apps/treasury/tables.py:39
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:28 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:28
#: apps/treasury/templates/treasury/sogecredit_detail.html:59 #: apps/treasury/templates/treasury/sogecredit_detail.html:59
#: apps/wei/tables.py:75 apps/wei/tables.py:101 #: apps/wei/tables.py:75 apps/wei/tables.py:102
#: apps/wei/templates/wei/weiregistration_confirm_delete.html:32 #: apps/wei/templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
@ -1358,27 +1370,31 @@ msgstr "Le bouton a bien été supprimé"
msgid "Unable to delete button " msgid "Unable to delete button "
msgstr "Impossible de supprimer le bouton " msgstr "Impossible de supprimer le bouton "
#: apps/note/views.py:34 #: apps/note/views.py:36
msgid "Transfer money" msgid "Transfer money"
msgstr "Transférer de l'argent" msgstr "Transférer de l'argent"
#: apps/note/views.py:74 #: apps/note/views.py:76
msgid "Create new button" msgid "Create new button"
msgstr "Créer un nouveau bouton" msgstr "Créer un nouveau bouton"
#: apps/note/views.py:83 #: apps/note/views.py:85
msgid "Search button" msgid "Search button"
msgstr "Chercher un bouton" msgstr "Chercher un bouton"
#: apps/note/views.py:106 #: apps/note/views.py:108
msgid "Update button" msgid "Update button"
msgstr "Modifier le bouton" msgstr "Modifier le bouton"
#: apps/note/views.py:143 note_kfet/templates/base.html:108 #: apps/note/views.py:145 note_kfet/templates/base.html:108
msgid "Consumptions" msgid "Consumptions"
msgstr "Consommations" msgstr "Consommations"
#: apps/note/views.py:179 #: apps/note/views.py:155
msgid "You can't see any button."
msgstr "Vous ne pouvez pas voir le moindre bouton."
#: apps/note/views.py:189
msgid "Search transactions" msgid "Search transactions"
msgstr "Rechercher des transactions" msgstr "Rechercher des transactions"
@ -1472,13 +1488,13 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du " "Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}." "modèle {app_label}.{model_name}."
#: apps/permission/signals.py:73 #: apps/permission/signals.py:73 apps/permission/views.py:66
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"You don't have the permission to add this instance of model {app_label}." "You don't have the permission to add an instance of model {app_label}."
"{model_name}." "{model_name}."
msgstr "" msgstr ""
"Vous n'avez pas la permission d'ajouter cette instance du modèle {app_label}." "Vous n'avez pas la permission d'ajouter une instance du modèle {app_label}."
"{model_name}." "{model_name}."
#: apps/permission/signals.py:101 #: apps/permission/signals.py:101
@ -1518,11 +1534,11 @@ msgstr "Requête :"
msgid "No associated permission" msgid "No associated permission"
msgstr "Pas de permission associée" msgstr "Pas de permission associée"
#: apps/permission/views.py:47 note_kfet/templates/base.html:143 #: apps/permission/views.py:73 note_kfet/templates/base.html:143
msgid "Rights" msgid "Rights"
msgstr "Droits" msgstr "Droits"
#: apps/permission/views.py:52 #: apps/permission/views.py:78
msgid "All rights" msgid "All rights"
msgstr "Tous les droits" msgstr "Tous les droits"
@ -1912,7 +1928,7 @@ msgid "No"
msgstr "Non" msgstr "Non"
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:8 #: apps/treasury/templates/treasury/invoice_confirm_delete.html:8
#: apps/treasury/views.py:143 #: apps/treasury/views.py:164
msgid "Delete invoice" msgid "Delete invoice"
msgstr "Supprimer la facture" msgstr "Supprimer la facture"
@ -1932,7 +1948,7 @@ msgid "Return to invoices list"
msgstr "Retour à la liste des factures" msgstr "Retour à la liste des factures"
#: apps/treasury/templates/treasury/invoice_form.html:6 #: apps/treasury/templates/treasury/invoice_form.html:6
#: apps/treasury/views.py:81 #: apps/treasury/views.py:90
msgid "Invoices list" msgid "Invoices list"
msgstr "Liste des factures" msgstr "Liste des factures"
@ -1969,7 +1985,7 @@ msgstr "Remise n°"
#: apps/treasury/templates/treasury/remittance_form.html:9 #: apps/treasury/templates/treasury/remittance_form.html:9
#: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7 #: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7
#: apps/treasury/views.py:224 #: apps/treasury/views.py:251
msgid "Remittances list" msgid "Remittances list"
msgstr "Liste des remises" msgstr "Liste des remises"
@ -2073,7 +2089,7 @@ msgstr ""
"demande de crédit." "demande de crédit."
#: apps/treasury/templates/treasury/sogecredit_detail.html:57 #: apps/treasury/templates/treasury/sogecredit_detail.html:57
#: apps/wei/tables.py:58 apps/wei/tables.py:59 apps/wei/tables.py:96 #: apps/wei/tables.py:58 apps/wei/tables.py:59 apps/wei/tables.py:98
msgid "Validate" msgid "Validate"
msgstr "Valider" msgstr "Valider"
@ -2095,27 +2111,32 @@ msgstr ""
msgid "Create new invoice" msgid "Create new invoice"
msgstr "Créer une nouvelle facture" msgstr "Créer une nouvelle facture"
#: apps/treasury/views.py:90 #: apps/treasury/views.py:101 apps/treasury/views.py:259
#: apps/treasury/views.py:381
msgid "You are not able to see the treasury interface."
msgstr "Vous n'êtes pas autorisé à voir l'interface de trésorerie."
#: apps/treasury/views.py:111
msgid "Update an invoice" msgid "Update an invoice"
msgstr "Modifier la facture" msgstr "Modifier la facture"
#: apps/treasury/views.py:203 #: apps/treasury/views.py:224
msgid "Create a new remittance" msgid "Create a new remittance"
msgstr "Créer une nouvelle remise" msgstr "Créer une nouvelle remise"
#: apps/treasury/views.py:274 #: apps/treasury/views.py:310
msgid "Update a remittance" msgid "Update a remittance"
msgstr "Modifier la remise" msgstr "Modifier la remise"
#: apps/treasury/views.py:297 #: apps/treasury/views.py:333
msgid "Attach a transaction to a remittance" msgid "Attach a transaction to a remittance"
msgstr "Joindre une transaction à une remise" msgstr "Joindre une transaction à une remise"
#: apps/treasury/views.py:341 #: apps/treasury/views.py:377
msgid "List of credits from the Société générale" msgid "List of credits from the Société générale"
msgstr "Liste des crédits de la Société générale" msgstr "Liste des crédits de la Société générale"
#: apps/treasury/views.py:375 #: apps/treasury/views.py:416
msgid "Manage credits from the Société générale" msgid "Manage credits from the Société générale"
msgstr "Gérer les crédits de la Société générale" msgstr "Gérer les crédits de la Société générale"
@ -2368,8 +2389,8 @@ msgstr "Télécharger au format PDF"
#: apps/wei/templates/wei/survey.html:12 #: apps/wei/templates/wei/survey.html:12
#: apps/wei/templates/wei/survey_closed.html:12 #: apps/wei/templates/wei/survey_closed.html:12
#: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:917 #: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:982
#: apps/wei/views.py:971 apps/wei/views.py:981 #: apps/wei/views.py:1036 apps/wei/views.py:1046
msgid "Survey WEI" msgid "Survey WEI"
msgstr "Questionnaire WEI" msgstr "Questionnaire WEI"
@ -2402,11 +2423,11 @@ msgstr "Prix du WEI / incluant l'adhésion BDE/Kfet (étudiants)"
msgid "WEI list" msgid "WEI list"
msgstr "Liste des WEI" msgstr "Liste des WEI"
#: apps/wei/templates/wei/weiclub_info.html:62 apps/wei/views.py:468 #: apps/wei/templates/wei/weiclub_info.html:62 apps/wei/views.py:507
msgid "Register 1A" msgid "Register 1A"
msgstr "Inscrire un 1A" msgstr "Inscrire un 1A"
#: apps/wei/templates/wei/weiclub_info.html:65 apps/wei/views.py:523 #: apps/wei/templates/wei/weiclub_info.html:65 apps/wei/views.py:574
msgid "Register 2A+" msgid "Register 2A+"
msgstr "Inscrire un 2A+" msgstr "Inscrire un 2A+"
@ -2418,7 +2439,7 @@ msgstr "Ajouter un bus"
msgid "View WEI" msgid "View WEI"
msgstr "Voir le WEI" msgstr "Voir le WEI"
#: apps/wei/templates/wei/weiclub_list.html:10 apps/wei/views.py:74 #: apps/wei/templates/wei/weiclub_list.html:10 apps/wei/views.py:77
msgid "Create WEI" msgid "Create WEI"
msgstr "Créer un WEI" msgstr "Créer un WEI"
@ -2584,95 +2605,95 @@ msgstr "Voir les adhésions validées ..."
msgid "Search WEI" msgid "Search WEI"
msgstr "Chercher un WEI" msgstr "Chercher un WEI"
#: apps/wei/views.py:94 #: apps/wei/views.py:106
msgid "WEI Detail" msgid "WEI Detail"
msgstr "Détails du WEI" msgstr "Détails du WEI"
#: apps/wei/views.py:189 #: apps/wei/views.py:201
msgid "View members of the WEI" msgid "View members of the WEI"
msgstr "Voir les membres du WEI" msgstr "Voir les membres du WEI"
#: apps/wei/views.py:217 #: apps/wei/views.py:229
msgid "Find WEI Membership" msgid "Find WEI Membership"
msgstr "Trouver une adhésion au WEI" msgstr "Trouver une adhésion au WEI"
#: apps/wei/views.py:227 #: apps/wei/views.py:239
msgid "View registrations to the WEI" msgid "View registrations to the WEI"
msgstr "Voir les inscriptions au WEI" msgstr "Voir les inscriptions au WEI"
#: apps/wei/views.py:251 #: apps/wei/views.py:263
msgid "Find WEI Registration" msgid "Find WEI Registration"
msgstr "Trouver une inscription au WEI" msgstr "Trouver une inscription au WEI"
#: apps/wei/views.py:262 #: apps/wei/views.py:274
msgid "Update the WEI" msgid "Update the WEI"
msgstr "Modifier le WEI" msgstr "Modifier le WEI"
#: apps/wei/views.py:283 #: apps/wei/views.py:295
msgid "Create new bus" msgid "Create new bus"
msgstr "Ajouter un nouveau bus" msgstr "Ajouter un nouveau bus"
#: apps/wei/views.py:314 #: apps/wei/views.py:333
msgid "Update bus" msgid "Update bus"
msgstr "Modifier le bus" msgstr "Modifier le bus"
#: apps/wei/views.py:344 #: apps/wei/views.py:363
msgid "Manage bus" msgid "Manage bus"
msgstr "Gérer le bus" msgstr "Gérer le bus"
#: apps/wei/views.py:371 #: apps/wei/views.py:390
msgid "Create new team" msgid "Create new team"
msgstr "Créer une nouvelle équipe" msgstr "Créer une nouvelle équipe"
#: apps/wei/views.py:403 #: apps/wei/views.py:430
msgid "Update team" msgid "Update team"
msgstr "Modifier l'équipe" msgstr "Modifier l'équipe"
#: apps/wei/views.py:434 #: apps/wei/views.py:461
msgid "Manage WEI team" msgid "Manage WEI team"
msgstr "Gérer l'équipe WEI" msgstr "Gérer l'équipe WEI"
#: apps/wei/views.py:456 #: apps/wei/views.py:483
msgid "Register first year student to the WEI" msgid "Register first year student to the WEI"
msgstr "Inscrire un 1A au WEI" msgstr "Inscrire un 1A au WEI"
#: apps/wei/views.py:489 apps/wei/views.py:560 #: apps/wei/views.py:528 apps/wei/views.py:611
msgid "This user is already registered to this WEI." msgid "This user is already registered to this WEI."
msgstr "Cette personne est déjà inscrite au WEI." msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:494 #: apps/wei/views.py:533
msgid "" msgid ""
"This user can't be in her/his first year since he/she has already participated " "This user can't be in her/his first year since he/she has already "
"to a WEI." "participated to a WEI."
msgstr "" msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'iel a déjà " "Cet utilisateur ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI." "participé à un WEI."
#: apps/wei/views.py:511 #: apps/wei/views.py:550
msgid "Register old student to the WEI" msgid "Register old student to the WEI"
msgstr "Inscrire un 2A+ au WEI" msgstr "Inscrire un 2A+ au WEI"
#: apps/wei/views.py:542 apps/wei/views.py:627 #: apps/wei/views.py:593 apps/wei/views.py:684
msgid "You already opened an account in the Société générale." msgid "You already opened an account in the Société générale."
msgstr "Vous avez déjà ouvert un compte auprès de la société générale." msgstr "Vous avez déjà ouvert un compte auprès de la société générale."
#: apps/wei/views.py:590 #: apps/wei/views.py:641
msgid "Update WEI Registration" msgid "Update WEI Registration"
msgstr "Modifier l'inscription WEI" msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:686 #: apps/wei/views.py:743
msgid "Delete WEI registration" msgid "Delete WEI registration"
msgstr "Supprimer l'inscription WEI" msgstr "Supprimer l'inscription WEI"
#: apps/wei/views.py:697 #: apps/wei/views.py:754
msgid "You don't have the right to delete this WEI registration." msgid "You don't have the right to delete this WEI registration."
msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI." msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI."
#: apps/wei/views.py:716 #: apps/wei/views.py:773
msgid "Validate WEI registration" msgid "Validate WEI registration"
msgstr "Valider l'inscription WEI" msgstr "Valider l'inscription WEI"
#: apps/wei/views.py:855 #: apps/wei/views.py:920
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "Cet utilisateur n'a pas donné son chèque de caution." msgstr "Cet utilisateur n'a pas donné son chèque de caution."