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, ...)
"""
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():
from scripts.management.commands.refresh_activities import Command as RefreshActivitiesCommand
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.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db.models import F, Q
from django.urls import reverse_lazy
from django.utils import timezone
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 note.models import Alias, NoteSpecial, NoteUser
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import ActivityForm, GuestForm
from .models import Activity, Entry, Guest
from .tables import ActivityTable, EntryTable, GuestTable
class ActivityCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class ActivityCreateView(LoginRequiredMixin, ProtectedCreateView):
model = Activity
form_class = ActivityForm
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):
form.instance.creater = self.request.user
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"]})
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
model = Guest
form_class = GuestForm
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):
context = super().get_context_data(**kwargs)
activity = context["form"].activity
@ -114,6 +136,24 @@ class ActivityInviteView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class ActivityEntryView(LoginRequiredMixin, TemplateView):
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):
context = super().get_context_data(**kwargs)

View File

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

View File

@ -3,6 +3,7 @@
from django.contrib.auth.models import User
from django.test import TestCase
from note.models import TransactionTemplate, TemplateCategory
"""
Test that login page still works
@ -16,6 +17,8 @@ class TemplateLoggedOutTests(TestCase):
class TemplateLoggedInTests(TestCase):
fixtures = ('initial', )
def setUp(self):
self.user = User.objects.create_superuser(
username="admin",
@ -48,5 +51,12 @@ class TemplateLoggedInTests(TestCase):
self.assertEqual(response.status_code, 200)
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/')
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.utils import timezone
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_tables2.views import SingleTableView
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 permission.backends import PermissionBackend
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 .models import Club, Membership
@ -295,7 +295,7 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
# ******************************* #
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create Club
"""
@ -304,6 +304,12 @@ class ClubCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
success_url = reverse_lazy('member:club_list')
extra_context = {"title": _("Create new club")}
def get_sample_object(self):
return Club(
name="",
email="",
)
def form_valid(self, form):
return super().form_valid(form)
@ -332,6 +338,14 @@ class ClubListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
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):
"""
@ -432,7 +446,7 @@ class ClubPictureUpdateView(PictureUpdateView):
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.
"""
@ -441,6 +455,19 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
template_name = 'member/add_members.html'
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):
context = super().get_context_data(**kwargs)
form = context['form']

View File

@ -1,10 +1,12 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import json
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db.models import Q, F
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView, DetailView
@ -145,6 +147,14 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
# Transaction history table
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):
return Transaction.objects.filter(
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:
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, ))

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 wei.models import WEIMembership, WEIRegistration, WEIClub, Bus, BusTeam
from .models import Permission
from ..models import Permission
class PermissionQueryTestCase(TestCase):

View File

@ -1,12 +1,14 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from datetime import date
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.forms import HiddenInput
from django.utils import timezone
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 .backends import PermissionBackend
@ -42,6 +44,30 @@ class ProtectQuerysetMixin:
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):
template_name = "permission/all_rights.html"
extra_context = {"title": _("Rights")}

View File

@ -8,28 +8,28 @@ from tempfile import mkdtemp
from crispy_forms.helper import FormHelper
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.forms import Form
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse_lazy
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.edit import BaseFormView, DeleteView
from django_tables2 import SingleTableView
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 permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create Invoice
"""
@ -37,6 +37,15 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = InvoiceForm
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):
context = super().get_context_data(**kwargs)
@ -72,7 +81,7 @@ class InvoiceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
return reverse_lazy('treasury:invoice_list')
class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
class InvoiceListView(LoginRequiredMixin, SingleTableView):
"""
List existing Invoices
"""
@ -80,6 +89,18 @@ class InvoiceListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView)
table_class = InvoiceTable
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):
"""
@ -194,7 +215,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
return response
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create Remittance
"""
@ -202,6 +223,12 @@ class RemittanceCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView)
form_class = RemittanceForm
extra_context = {"title": _("Create a new remittance")}
def get_sample_object(self):
return Remittance(
remittance_type_id=1,
comment="",
)
def get_success_url(self):
return reverse_lazy('treasury:remittance_list')
@ -223,6 +250,15 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
template_name = "treasury/remittance_list.html"
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):
context = super().get_context_data(**kwargs)
@ -340,6 +376,11 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
table_class = SogeCreditTable
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):
"""
Filter the table with the given parameter.

View File

@ -4,7 +4,7 @@
import os
import shutil
import subprocess
from datetime import datetime, date
from datetime import datetime, date, timedelta
from tempfile import mkdtemp
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.utils import timezone
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.views.generic.edit import BaseFormView, DeleteView
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_kfet.settings import BASE_DIR
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms.registration import WEIChooseBusForm
from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam, WEIRole
@ -58,6 +58,8 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["can_create_wei"] = PermissionBackend.check_perm(self.request.user, "wei.add_weiclub", WEIClub(
name="",
email="weiclub@example.com",
year=0,
date_start=timezone.now().date(),
date_end=timezone.now().date(),
@ -65,14 +67,24 @@ class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
return context
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create WEI
"""
model = WEIClub
form_class = WEIForm
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):
form.instance.requires_membership = True
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})
class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create Bus
"""
@ -282,6 +294,13 @@ class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = BusForm
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):
wei = WEIClub.objects.get(pk=self.kwargs["pk"])
today = date.today()
@ -362,7 +381,7 @@ class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
return context
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Create BusTeam
"""
@ -370,6 +389,14 @@ class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = BusTeamForm
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):
wei = WEIClub.objects.get(buses__pk=self.kwargs["pk"])
today = date.today()
@ -447,7 +474,7 @@ class BusTeamManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
return context
class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Register a new user to the WEI
"""
@ -455,6 +482,18 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = WEIRegistrationForm
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):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
today = date.today()
@ -502,7 +541,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
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
"""
@ -510,6 +549,18 @@ class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
form_class = WEIRegistrationForm
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):
wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
today = date.today()
@ -713,7 +764,7 @@ class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Delete
return reverse_lazy('wei:wei_detail', args=(self.object.wei.pk,))
class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, ProtectedCreateView):
"""
Validate WEI Registration
"""
@ -721,6 +772,17 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
form_class = WEIMembershipForm
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):
wei = WEIRegistration.objects.get(pk=self.kwargs["pk"]).wei
today = date.today()

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\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"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -327,27 +327,39 @@ msgstr ""
msgid "All activities"
msgstr ""
#: apps/activity/views.py:25
#: apps/activity/views.py:26
msgid "Create new activity"
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"
msgstr ""
#: apps/activity/views.py:65
#: apps/activity/views.py:78
msgid "Activity detail"
msgstr ""
#: apps/activity/views.py:82
#: apps/activity/views.py:95
msgid "Update activity"
msgstr ""
#: apps/activity/views.py:96
#: apps/activity/views.py:118
msgid "Invite guest to the activity \"{}\""
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 \"{}\""
msgstr ""
@ -682,7 +694,7 @@ msgstr ""
msgid "The role {role} does not apply to the club {club}."
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"
msgstr ""
@ -774,11 +786,11 @@ msgstr ""
msgid "View Profile"
msgstr ""
#: apps/member/templates/member/club_list.html:9
#: apps/member/templates/member/club_list.html:11
msgid "Create club"
msgstr ""
#: apps/member/templates/member/club_list.html:16
#: apps/member/templates/member/club_list.html:19
msgid "Club listing"
msgstr ""
@ -890,7 +902,7 @@ msgstr ""
msgid "Search user"
msgstr ""
#: apps/member/views.py:205 apps/member/views.py:391
#: apps/member/views.py:205 apps/member/views.py:405
msgid "Note aliases"
msgstr ""
@ -902,47 +914,47 @@ msgstr ""
msgid "Create new club"
msgstr ""
#: apps/member/views.py:317
#: apps/member/views.py:323
msgid "Search club"
msgstr ""
#: apps/member/views.py:342
#: apps/member/views.py:356
msgid "Club detail"
msgstr ""
#: apps/member/views.py:408
#: apps/member/views.py:422
msgid "Update club"
msgstr ""
#: apps/member/views.py:442
#: apps/member/views.py:456
msgid "Add new member to the club"
msgstr ""
#: apps/member/views.py:583 apps/wei/views.py:861
#: apps/member/views.py:610 apps/wei/views.py:926
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
msgstr ""
#: apps/member/views.py:596
#: apps/member/views.py:623
msgid "The membership must start after {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:601
#: apps/member/views.py:628
msgid "The membership must begin before {:%m-%d-%Y}."
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: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."
msgstr ""
#: apps/member/views.py:706
#: apps/member/views.py:733
msgid "Manage roles of an user in the club"
msgstr ""
#: apps/member/views.py:731
#: apps/member/views.py:758
msgid "Members of the club"
msgstr ""
@ -1223,7 +1235,7 @@ msgstr ""
#: 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/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
msgid "Delete"
msgstr ""
@ -1340,27 +1352,31 @@ msgstr ""
msgid "Unable to delete button "
msgstr ""
#: apps/note/views.py:34
#: apps/note/views.py:36
msgid "Transfer money"
msgstr ""
#: apps/note/views.py:74
#: apps/note/views.py:76
msgid "Create new button"
msgstr ""
#: apps/note/views.py:83
#: apps/note/views.py:85
msgid "Search button"
msgstr ""
#: apps/note/views.py:106
#: apps/note/views.py:108
msgid "Update button"
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"
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"
msgstr ""
@ -1448,10 +1464,10 @@ msgid ""
"of model {app_label}.{model_name}."
msgstr ""
#: apps/permission/signals.py:73
#: apps/permission/signals.py:73 apps/permission/views.py:66
#, python-brace-format
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}."
msgstr ""
@ -1490,11 +1506,11 @@ msgstr ""
msgid "No associated permission"
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"
msgstr ""
#: apps/permission/views.py:52
#: apps/permission/views.py:78
msgid "All rights"
msgstr ""
@ -1864,7 +1880,7 @@ msgid "No"
msgstr ""
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:8
#: apps/treasury/views.py:143
#: apps/treasury/views.py:164
msgid "Delete invoice"
msgstr ""
@ -1882,7 +1898,7 @@ msgid "Return to invoices list"
msgstr ""
#: apps/treasury/templates/treasury/invoice_form.html:6
#: apps/treasury/views.py:81
#: apps/treasury/views.py:90
msgid "Invoices list"
msgstr ""
@ -1916,7 +1932,7 @@ msgstr ""
#: apps/treasury/templates/treasury/remittance_form.html:9
#: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7
#: apps/treasury/views.py:224
#: apps/treasury/views.py:251
msgid "Remittances list"
msgstr ""
@ -2009,7 +2025,7 @@ msgid "Please ask the user to credit its note before deleting this credit."
msgstr ""
#: 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"
msgstr ""
@ -2029,27 +2045,32 @@ msgstr ""
msgid "Create new invoice"
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"
msgstr ""
#: apps/treasury/views.py:203
#: apps/treasury/views.py:224
msgid "Create a new remittance"
msgstr ""
#: apps/treasury/views.py:274
#: apps/treasury/views.py:310
msgid "Update a remittance"
msgstr ""
#: apps/treasury/views.py:297
#: apps/treasury/views.py:333
msgid "Attach a transaction to a remittance"
msgstr ""
#: apps/treasury/views.py:341
#: apps/treasury/views.py:377
msgid "List of credits from the Société générale"
msgstr ""
#: apps/treasury/views.py:375
#: apps/treasury/views.py:416
msgid "Manage credits from the Société générale"
msgstr ""
@ -2287,8 +2308,8 @@ msgstr ""
#: apps/wei/templates/wei/survey.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/views.py:971 apps/wei/views.py:981
#: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:982
#: apps/wei/views.py:1036 apps/wei/views.py:1046
msgid "Survey WEI"
msgstr ""
@ -2320,11 +2341,11 @@ msgstr ""
msgid "WEI list"
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"
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+"
msgstr ""
@ -2336,7 +2357,7 @@ msgstr ""
msgid "View WEI"
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"
msgstr ""
@ -2489,93 +2510,93 @@ msgstr ""
msgid "Search WEI"
msgstr ""
#: apps/wei/views.py:94
#: apps/wei/views.py:106
msgid "WEI Detail"
msgstr ""
#: apps/wei/views.py:189
#: apps/wei/views.py:201
msgid "View members of the WEI"
msgstr ""
#: apps/wei/views.py:217
#: apps/wei/views.py:229
msgid "Find WEI Membership"
msgstr ""
#: apps/wei/views.py:227
#: apps/wei/views.py:239
msgid "View registrations to the WEI"
msgstr ""
#: apps/wei/views.py:251
#: apps/wei/views.py:263
msgid "Find WEI Registration"
msgstr ""
#: apps/wei/views.py:262
#: apps/wei/views.py:274
msgid "Update the WEI"
msgstr ""
#: apps/wei/views.py:283
#: apps/wei/views.py:295
msgid "Create new bus"
msgstr ""
#: apps/wei/views.py:314
#: apps/wei/views.py:333
msgid "Update bus"
msgstr ""
#: apps/wei/views.py:344
#: apps/wei/views.py:363
msgid "Manage bus"
msgstr ""
#: apps/wei/views.py:371
#: apps/wei/views.py:390
msgid "Create new team"
msgstr ""
#: apps/wei/views.py:403
#: apps/wei/views.py:430
msgid "Update team"
msgstr ""
#: apps/wei/views.py:434
#: apps/wei/views.py:461
msgid "Manage WEI team"
msgstr ""
#: apps/wei/views.py:456
#: apps/wei/views.py:483
msgid "Register first year student to the WEI"
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."
msgstr ""
#: apps/wei/views.py:494
#: apps/wei/views.py:533
msgid ""
"This user can't be in her/his first year since he/she has already participated "
"to a WEI."
"This user can't be in her/his first year since he/she has already "
"participated to a WEI."
msgstr ""
#: apps/wei/views.py:511
#: apps/wei/views.py:550
msgid "Register old student to the WEI"
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."
msgstr ""
#: apps/wei/views.py:590
#: apps/wei/views.py:641
msgid "Update WEI Registration"
msgstr ""
#: apps/wei/views.py:686
#: apps/wei/views.py:743
msgid "Delete WEI registration"
msgstr ""
#: apps/wei/views.py:697
#: apps/wei/views.py:754
msgid "You don't have the right to delete this WEI registration."
msgstr ""
#: apps/wei/views.py:716
#: apps/wei/views.py:773
msgid "Validate WEI registration"
msgstr ""
#: apps/wei/views.py:855
#: apps/wei/views.py:920
msgid "This user didn't give her/his caution check."
msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\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"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -328,27 +328,39 @@ msgstr "Nouvelle activité"
msgid "All activities"
msgstr "Toutes les activités"
#: apps/activity/views.py:25
#: apps/activity/views.py:26
msgid "Create new activity"
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"
msgstr "Activités"
#: apps/activity/views.py:65
#: apps/activity/views.py:78
msgid "Activity detail"
msgstr "Détails de l'activité"
#: apps/activity/views.py:82
#: apps/activity/views.py:95
msgid "Update activity"
msgstr "Modifier l'activité"
#: apps/activity/views.py:96
#: apps/activity/views.py:118
msgid "Invite guest to the activity \"{}\""
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 \"{}\""
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}."
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"
msgstr "L'utilisateur est déjà membre du club"
@ -783,11 +795,11 @@ msgstr "Éditer"
msgid "View Profile"
msgstr "Voir le profil"
#: apps/member/templates/member/club_list.html:9
#: apps/member/templates/member/club_list.html:11
msgid "Create 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"
msgstr "Liste des clubs"
@ -899,7 +911,7 @@ msgstr "Détails de l'utilisateur"
msgid "Search user"
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"
msgstr "Alias de la note"
@ -911,23 +923,23 @@ msgstr "Modifier la photo de la note"
msgid "Create new club"
msgstr "Créer un nouveau club"
#: apps/member/views.py:317
#: apps/member/views.py:323
msgid "Search club"
msgstr "Chercher un club"
#: apps/member/views.py:342
#: apps/member/views.py:356
msgid "Club detail"
msgstr "Détails du club"
#: apps/member/views.py:408
#: apps/member/views.py:422
msgid "Update club"
msgstr "Modifier le club"
#: apps/member/views.py:442
#: apps/member/views.py:456
msgid "Add new member to the 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 ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@ -935,25 +947,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif."
#: apps/member/views.py:596
#: apps/member/views.py:623
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:601
#: apps/member/views.py:628
msgid "The membership must begin before {:%m-%d-%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: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."
msgstr "Ce champ est requis."
#: apps/member/views.py:706
#: apps/member/views.py:733
msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club"
#: apps/member/views.py:731
#: apps/member/views.py:758
msgid "Members of the 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/treasury/templates/treasury/invoice_confirm_delete.html:28
#: 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
msgid "Delete"
msgstr "Supprimer"
@ -1358,27 +1370,31 @@ msgstr "Le bouton a bien été supprimé"
msgid "Unable to delete button "
msgstr "Impossible de supprimer le bouton "
#: apps/note/views.py:34
#: apps/note/views.py:36
msgid "Transfer money"
msgstr "Transférer de l'argent"
#: apps/note/views.py:74
#: apps/note/views.py:76
msgid "Create new button"
msgstr "Créer un nouveau bouton"
#: apps/note/views.py:83
#: apps/note/views.py:85
msgid "Search button"
msgstr "Chercher un bouton"
#: apps/note/views.py:106
#: apps/note/views.py:108
msgid "Update button"
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"
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"
msgstr "Rechercher des transactions"
@ -1472,13 +1488,13 @@ msgstr ""
"Vous n'avez pas la permission de modifier le champ {field} sur l'instance du "
"modèle {app_label}.{model_name}."
#: apps/permission/signals.py:73
#: apps/permission/signals.py:73 apps/permission/views.py:66
#, python-brace-format
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}."
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}."
#: apps/permission/signals.py:101
@ -1518,11 +1534,11 @@ msgstr "Requête :"
msgid "No associated permission"
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"
msgstr "Droits"
#: apps/permission/views.py:52
#: apps/permission/views.py:78
msgid "All rights"
msgstr "Tous les droits"
@ -1912,7 +1928,7 @@ msgid "No"
msgstr "Non"
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:8
#: apps/treasury/views.py:143
#: apps/treasury/views.py:164
msgid "Delete invoice"
msgstr "Supprimer la facture"
@ -1932,7 +1948,7 @@ msgid "Return to invoices list"
msgstr "Retour à la liste des factures"
#: apps/treasury/templates/treasury/invoice_form.html:6
#: apps/treasury/views.py:81
#: apps/treasury/views.py:90
msgid "Invoices list"
msgstr "Liste des factures"
@ -1969,7 +1985,7 @@ msgstr "Remise n°"
#: apps/treasury/templates/treasury/remittance_form.html:9
#: apps/treasury/templates/treasury/specialtransactionproxy_form.html:7
#: apps/treasury/views.py:224
#: apps/treasury/views.py:251
msgid "Remittances list"
msgstr "Liste des remises"
@ -2073,7 +2089,7 @@ msgstr ""
"demande de crédit."
#: 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"
msgstr "Valider"
@ -2095,27 +2111,32 @@ msgstr ""
msgid "Create new invoice"
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"
msgstr "Modifier la facture"
#: apps/treasury/views.py:203
#: apps/treasury/views.py:224
msgid "Create a new remittance"
msgstr "Créer une nouvelle remise"
#: apps/treasury/views.py:274
#: apps/treasury/views.py:310
msgid "Update a remittance"
msgstr "Modifier la remise"
#: apps/treasury/views.py:297
#: apps/treasury/views.py:333
msgid "Attach a transaction to a remittance"
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"
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"
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_closed.html:12
#: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:917
#: apps/wei/views.py:971 apps/wei/views.py:981
#: apps/wei/templates/wei/survey_end.html:12 apps/wei/views.py:982
#: apps/wei/views.py:1036 apps/wei/views.py:1046
msgid "Survey WEI"
msgstr "Questionnaire WEI"
@ -2402,11 +2423,11 @@ msgstr "Prix du WEI / incluant l'adhésion BDE/Kfet (étudiants)"
msgid "WEI list"
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"
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+"
msgstr "Inscrire un 2A+"
@ -2418,7 +2439,7 @@ msgstr "Ajouter un bus"
msgid "View 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"
msgstr "Créer un WEI"
@ -2584,95 +2605,95 @@ msgstr "Voir les adhésions validées ..."
msgid "Search WEI"
msgstr "Chercher un WEI"
#: apps/wei/views.py:94
#: apps/wei/views.py:106
msgid "WEI Detail"
msgstr "Détails du WEI"
#: apps/wei/views.py:189
#: apps/wei/views.py:201
msgid "View members of the WEI"
msgstr "Voir les membres du WEI"
#: apps/wei/views.py:217
#: apps/wei/views.py:229
msgid "Find WEI Membership"
msgstr "Trouver une adhésion au WEI"
#: apps/wei/views.py:227
#: apps/wei/views.py:239
msgid "View registrations to the WEI"
msgstr "Voir les inscriptions au WEI"
#: apps/wei/views.py:251
#: apps/wei/views.py:263
msgid "Find WEI Registration"
msgstr "Trouver une inscription au WEI"
#: apps/wei/views.py:262
#: apps/wei/views.py:274
msgid "Update the WEI"
msgstr "Modifier le WEI"
#: apps/wei/views.py:283
#: apps/wei/views.py:295
msgid "Create new bus"
msgstr "Ajouter un nouveau bus"
#: apps/wei/views.py:314
#: apps/wei/views.py:333
msgid "Update bus"
msgstr "Modifier le bus"
#: apps/wei/views.py:344
#: apps/wei/views.py:363
msgid "Manage bus"
msgstr "Gérer le bus"
#: apps/wei/views.py:371
#: apps/wei/views.py:390
msgid "Create new team"
msgstr "Créer une nouvelle équipe"
#: apps/wei/views.py:403
#: apps/wei/views.py:430
msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/wei/views.py:434
#: apps/wei/views.py:461
msgid "Manage WEI team"
msgstr "Gérer l'équipe WEI"
#: apps/wei/views.py:456
#: apps/wei/views.py:483
msgid "Register first year student to the 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."
msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:494
#: apps/wei/views.py:533
msgid ""
"This user can't be in her/his first year since he/she has already participated "
"to a WEI."
"This user can't be in her/his first year since he/she has already "
"participated to a WEI."
msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI."
#: apps/wei/views.py:511
#: apps/wei/views.py:550
msgid "Register old student to the 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."
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"
msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:686
#: apps/wei/views.py:743
msgid "Delete WEI registration"
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."
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"
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."
msgstr "Cet utilisateur n'a pas donné son chèque de caution."