diff --git a/apps/note/api/views.py b/apps/note/api/views.py
index f230a646..fc4a0e8f 100644
--- a/apps/note/api/views.py
+++ b/apps/note/api/views.py
@@ -5,6 +5,7 @@ from django.db.models import Q
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter, SearchFilter
from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet
+from rest_framework import viewsets
from .serializers import NotePolymorphicSerializer, AliasSerializer, TemplateCategorySerializer, \
TransactionTemplateSerializer, TransactionPolymorphicSerializer
@@ -81,7 +82,7 @@ class TemplateCategoryViewSet(ReadProtectedModelViewSet):
search_fields = ['$name', ]
-class TransactionTemplateViewSet(ReadProtectedModelViewSet):
+class TransactionTemplateViewSet(viewsets.ModelViewSet):
"""
REST API View set.
The djangorestframework plugin will get all `TransactionTemplate` objects, serialize it to JSON with the given serializer,
@@ -89,8 +90,9 @@ class TransactionTemplateViewSet(ReadProtectedModelViewSet):
"""
queryset = TransactionTemplate.objects.all()
serializer_class = TransactionTemplateSerializer
- filter_backends = [DjangoFilterBackend]
+ filter_backends = [SearchFilter, DjangoFilterBackend]
filterset_fields = ['name', 'amount', 'display', 'category', ]
+ search_fields = ['$name', ]
class TransactionViewSet(ReadProtectedModelViewSet):
diff --git a/apps/note/tables.py b/apps/note/tables.py
index b9dac051..20054d2c 100644
--- a/apps/note/tables.py
+++ b/apps/note/tables.py
@@ -9,7 +9,7 @@ from django_tables2.utils import A
from django.utils.translation import gettext_lazy as _
from .models.notes import Alias
-from .models.transactions import Transaction
+from .models.transactions import Transaction, TransactionTemplate
from .templatetags.pretty_money import pretty_money
@@ -57,6 +57,12 @@ class HistoryTable(tables.Table):
return "✔" if value else "✖"
+# function delete_button(id) provided in template file
+DELETE_TEMPLATE = """
+
+"""
+
+
class AliasTable(tables.Table):
class Meta:
attrs = {
@@ -69,9 +75,41 @@ class AliasTable(tables.Table):
show_header = False
name = tables.Column(attrs={'td': {'class': 'text-center'}})
+ # delete = tables.TemplateColumn(template_code=delete_template,
+ # attrs={'td':{'class': 'col-sm-1'}})
+
delete = tables.LinkColumn('member:user_alias_delete',
args=[A('pk')],
attrs={
'td': {'class': 'col-sm-2'},
'a': {'class': 'btn btn-danger'}},
text='delete', accessor='pk')
+
+
+class ButtonTable(tables.Table):
+ class Meta:
+ attrs = {
+ 'class':
+ 'table table-bordered condensed table-hover'
+ }
+ row_attrs = {
+ 'class': lambda record: 'table-row ' + 'table-success' if record.display else 'table-danger',
+ 'id': lambda record: "row-" + str(record.pk),
+ 'data-href': lambda record: record.pk
+ }
+
+ model = TransactionTemplate
+
+ edit = tables.LinkColumn('note:template_update',
+ args=[A('pk')],
+ attrs={'td': {'class': 'col-sm-1'},
+ 'a': {'class': 'btn btn-primary'}},
+ text=_('edit'),
+ accessor='pk')
+
+ delete = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
+ extra_context={"delete_trans": _('delete')},
+ attrs={'td': {'class': 'col-sm-1'}})
+
+ def render_amount(self, value):
+ return pretty_money(value)
diff --git a/apps/note/urls.py b/apps/note/urls.py
index fea911f6..59316069 100644
--- a/apps/note/urls.py
+++ b/apps/note/urls.py
@@ -8,7 +8,7 @@ from .models import Note
app_name = 'note'
urlpatterns = [
- path('transfer/', views.TransactionCreate.as_view(), name='transfer'),
+ path('transfer/', views.TransactionCreateView.as_view(), name='transfer'),
path('buttons/create/', views.TransactionTemplateCreateView.as_view(), name='template_create'),
path('buttons/update//', views.TransactionTemplateUpdateView.as_view(), name='template_update'),
path('buttons/', views.TransactionTemplateListView.as_view(), name='template_list'),
diff --git a/apps/note/views.py b/apps/note/views.py
index 84df2bd7..ddf5ee6f 100644
--- a/apps/note/views.py
+++ b/apps/note/views.py
@@ -6,22 +6,25 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
-from django.views.generic import CreateView, ListView, UpdateView
+from django.views.generic import CreateView, UpdateView
from django_tables2 import SingleTableView
+from django.urls import reverse_lazy
from permission.backends import PermissionBackend
from .forms import TransactionTemplateForm
from .models import Transaction, TransactionTemplate, Alias, RecurrentTransaction, NoteSpecial
from .models.transactions import SpecialTransaction
-from .tables import HistoryTable
+from .tables import HistoryTable, ButtonTable
-class TransactionCreate(LoginRequiredMixin, SingleTableView):
+class TransactionCreateView(LoginRequiredMixin, SingleTableView):
"""
- Show transfer page
+ View for the creation of Transaction between two note which are not :models:`transactions.RecurrentTransaction`.
+ e.g. for donation/transfer between people and clubs or for credit/debit with :models:`note.NoteSpecial`
"""
template_name = "note/transaction_form.html"
+ model = Transaction
# Transaction history table
table_class = HistoryTable
table_pagination = {"per_page": 50}
@@ -46,13 +49,14 @@ class TransactionCreate(LoginRequiredMixin, SingleTableView):
class NoteAutocomplete(autocomplete.Select2QuerySetView):
"""
- Auto complete note by aliases
+ Auto complete note by aliases. Used in every search field for note
+ ex: :view:`ConsoView`, :view:`TransactionCreateView`
"""
def get_queryset(self):
"""
- Quand une personne cherche un alias, une requête est envoyée sur l'API dédiée à l'auto-complétion.
- Cette fonction récupère la requête, et renvoie la liste filtrée des aliases.
+ When someone look for an :models:`note.Alias`, a query is sent to the dedicated API.
+ This function handles the result and return a filtered list of aliases.
"""
# Un utilisateur non connecté n'a accès à aucune information
if not self.request.user.is_authenticated:
@@ -81,6 +85,10 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView):
return qs
def get_result_label(self, result):
+ """
+ Show the selected alias and the username associated
+ (aka. )
+ """
# Gère l'affichage de l'alias dans la recherche
res = result.name
note_name = str(result.note)
@@ -89,7 +97,9 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView):
return res
def get_result_value(self, result):
- # Le résultat renvoyé doit être l'identifiant de la note, et non de l'alias
+ """
+ The value used for the transactions will be the id of the Note.
+ """
return str(result.note.pk)
@@ -99,14 +109,15 @@ class TransactionTemplateCreateView(LoginRequiredMixin, CreateView):
"""
model = TransactionTemplate
form_class = TransactionTemplateForm
+ success_url = reverse_lazy('note:template_list')
-class TransactionTemplateListView(LoginRequiredMixin, ListView):
+class TransactionTemplateListView(LoginRequiredMixin, SingleTableView):
"""
List TransactionsTemplates
"""
model = TransactionTemplate
- form_class = TransactionTemplateForm
+ table_class = ButtonTable
class TransactionTemplateUpdateView(LoginRequiredMixin, UpdateView):
@@ -114,11 +125,13 @@ class TransactionTemplateUpdateView(LoginRequiredMixin, UpdateView):
"""
model = TransactionTemplate
form_class = TransactionTemplateForm
+ success_url = reverse_lazy('note:template_list')
class ConsoView(LoginRequiredMixin, SingleTableView):
"""
- Consume
+ The Magic View that make people pay their beer and burgers.
+ (Most of the magic happens in the dark world of Javascript see consos.js)
"""
template_name = "note/conso_form.html"
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
index 3ca2b248..4c7de16d 100644
--- a/apps/permission/fixtures/initial.json
+++ b/apps/permission/fixtures/initial.json
@@ -650,4 +650,4 @@
]
}
}
-]
\ No newline at end of file
+]
diff --git a/apps/permission/permissions.py b/apps/permission/permissions.py
index d9816a63..9f6d8cd2 100644
--- a/apps/permission/permissions.py
+++ b/apps/permission/permissions.py
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from rest_framework.permissions import DjangoObjectPermissions
+from .backends import PermissionBackend
SAFE_METHODS = ('HEAD', 'OPTIONS', )
@@ -41,8 +42,8 @@ class StrongDjangoObjectPermissions(DjangoObjectPermissions):
user = request.user
perms = self.get_required_object_permissions(request.method, model_cls)
-
- if not user.has_perms(perms, obj):
+ # if not user.has_perms(perms, obj):
+ if not all(PermissionBackend().has_perm(user, perm, obj) for perm in perms):
# If the user does not have permissions we need to determine if
# they have read permissions to see 403, or not, and simply see
# a 404 response.
diff --git a/apps/scripts b/apps/scripts
new file mode 160000
index 00000000..b9fdced3
--- /dev/null
+++ b/apps/scripts
@@ -0,0 +1 @@
+Subproject commit b9fdced3c2ce34168b8f0d6004a20a69ca16e0de
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 84bd3249..d49b2542 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -128,7 +128,6 @@ PASSWORD_HASHERS = [
AUTHENTICATION_BACKENDS = (
'permission.backends.PermissionBackend', # Custom role-based permission system
- 'cas.backends.CASBackend', # For CAS connections
)
REST_FRAMEWORK = {
diff --git a/templates/base.html b/templates/base.html
index 384535b2..62fc9c58 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -79,6 +79,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% trans 'Consumptions' %}
{% endif %}
+
- Vous pouvez aussi vous connecter via l'authentification centralisée en suivant ce lien.
+ {% trans "You can also register via the central authentification server " %}
+ {% trans "using this link "%}