mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
Merge remote-tracking branch 'origin/master' into activity
This commit is contained in:
commit
dadd840645
@ -4,6 +4,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@ -67,6 +68,13 @@ class Club(models.Model):
|
|||||||
email = models.EmailField(
|
email = models.EmailField(
|
||||||
verbose_name=_('email'),
|
verbose_name=_('email'),
|
||||||
)
|
)
|
||||||
|
parent_club = models.ForeignKey(
|
||||||
|
'self',
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
verbose_name=_('parent club'),
|
||||||
|
)
|
||||||
|
|
||||||
# Memberships
|
# Memberships
|
||||||
membership_fee = models.PositiveIntegerField(
|
membership_fee = models.PositiveIntegerField(
|
||||||
@ -158,6 +166,12 @@ class Membership(models.Model):
|
|||||||
else:
|
else:
|
||||||
return self.date_start.toordinal() <= datetime.datetime.now().toordinal()
|
return self.date_start.toordinal() <= datetime.datetime.now().toordinal()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.club.parent_club is not None:
|
||||||
|
if not Membership.objects.filter(user=self.user, club=self.club.parent_club):
|
||||||
|
raise ValidationError(_('User is not a member of the parent club'))
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('membership')
|
verbose_name = _('membership')
|
||||||
verbose_name_plural = _('memberships')
|
verbose_name_plural = _('memberships')
|
||||||
|
@ -14,12 +14,12 @@ urlpatterns = [
|
|||||||
path('club/create/', views.ClubCreateView.as_view(), name="club_create"),
|
path('club/create/', views.ClubCreateView.as_view(), name="club_create"),
|
||||||
path('club/<int:pk>/update', views.ClubUpdateView.as_view(), name="club_update"),
|
path('club/<int:pk>/update', views.ClubUpdateView.as_view(), name="club_update"),
|
||||||
path('club/<int:pk>/update_pic', views.ClubPictureUpdateView.as_view(), name="club_update_pic"),
|
path('club/<int:pk>/update_pic', views.ClubPictureUpdateView.as_view(), name="club_update_pic"),
|
||||||
|
path('club/<int:pk>/aliases', views.ClubAliasView.as_view(), name="club_alias"),
|
||||||
path('user/', views.UserListView.as_view(), name="user_list"),
|
path('user/', views.UserListView.as_view(), name="user_list"),
|
||||||
path('user/<int:pk>', views.UserDetailView.as_view(), name="user_detail"),
|
path('user/<int:pk>', views.UserDetailView.as_view(), name="user_detail"),
|
||||||
path('user/<int:pk>/update', views.UserUpdateView.as_view(), name="user_update_profile"),
|
path('user/<int:pk>/update', views.UserUpdateView.as_view(), name="user_update_profile"),
|
||||||
path('user/<int:pk>/update_pic', views.ProfilePictureUpdateView.as_view(), name="user_update_pic"),
|
path('user/<int:pk>/update_pic', views.ProfilePictureUpdateView.as_view(), name="user_update_pic"),
|
||||||
path('user/<int:pk>/aliases', views.AliasView.as_view(), name="user_alias"),
|
path('user/<int:pk>/aliases', views.ProfileAliasView.as_view(), name="user_alias"),
|
||||||
path('user/aliases/delete/<int:pk>', views.DeleteAliasView.as_view(), name="user_alias_delete"),
|
|
||||||
path('manage-auth-token/', views.ManageAuthTokens.as_view(), name='auth_token'),
|
path('manage-auth-token/', views.ManageAuthTokens.as_view(), name='auth_token'),
|
||||||
# API for the user autocompleter
|
# API for the user autocompleter
|
||||||
path('user/user-autocomplete', views.UserAutocomplete.as_view(), name="user_autocomplete"),
|
path('user/user-autocomplete', views.UserAutocomplete.as_view(), name="user_autocomplete"),
|
||||||
|
@ -20,7 +20,8 @@ from django.views.generic import CreateView, DetailView, UpdateView, TemplateVie
|
|||||||
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
|
||||||
from note.forms import AliasForm, ImageForm
|
from note.forms import ImageForm
|
||||||
|
#from note.forms import AliasForm, ImageForm
|
||||||
from note.models import Alias, NoteUser
|
from note.models import Alias, NoteUser
|
||||||
from note.models.transactions import Transaction
|
from note.models.transactions import Transaction
|
||||||
from note.tables import HistoryTable, AliasTable
|
from note.tables import HistoryTable, AliasTable
|
||||||
@ -143,10 +144,6 @@ class UserDetailView(LoginRequiredMixin, DetailView):
|
|||||||
club_list = \
|
club_list = \
|
||||||
Membership.objects.all().filter(user=user).only("club")
|
Membership.objects.all().filter(user=user).only("club")
|
||||||
context['club_list'] = ClubTable(club_list)
|
context['club_list'] = ClubTable(club_list)
|
||||||
context['title'] = _("Account #%(id)s: %(username)s") % {
|
|
||||||
'id': user.pk,
|
|
||||||
'username': user.username,
|
|
||||||
}
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@ -171,57 +168,18 @@ class UserListView(LoginRequiredMixin, SingleTableView):
|
|||||||
context["filter"] = self.filter
|
context["filter"] = self.filter
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class AliasView(LoginRequiredMixin, FormMixin, DetailView):
|
class ProfileAliasView(LoginRequiredMixin, DetailView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'member/profile_alias.html'
|
template_name = 'member/profile_alias.html'
|
||||||
context_object_name = 'user_object'
|
context_object_name = 'user_object'
|
||||||
form_class = AliasForm
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
note = context['user_object'].note
|
note = context['object'].note
|
||||||
context["aliases"] = AliasTable(note.alias_set.all())
|
context["aliases"] = AliasTable(note.alias_set.all())
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse_lazy('member:user_alias', kwargs={'pk': self.object.id})
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
self.object = self.get_object()
|
|
||||||
form = self.get_form()
|
|
||||||
if form.is_valid():
|
|
||||||
return self.form_valid(form)
|
|
||||||
else:
|
|
||||||
return self.form_invalid(form)
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
|
||||||
alias = form.save(commit=False)
|
|
||||||
alias.note = self.object.note
|
|
||||||
alias.save()
|
|
||||||
return super().form_valid(form)
|
|
||||||
|
|
||||||
|
|
||||||
class DeleteAliasView(LoginRequiredMixin, DeleteView):
|
|
||||||
model = Alias
|
|
||||||
|
|
||||||
def delete(self, request, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
self.object = self.get_object()
|
|
||||||
self.object.delete()
|
|
||||||
except ValidationError as e:
|
|
||||||
# TODO: pass message to redirected view.
|
|
||||||
messages.error(self.request, str(e))
|
|
||||||
else:
|
|
||||||
messages.success(self.request, _("Alias successfully deleted"))
|
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse_lazy('member:user_alias', kwargs={'pk': self.object.note.user.pk})
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
return self.post(request, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class PictureUpdateView(LoginRequiredMixin, FormMixin, DetailView):
|
class PictureUpdateView(LoginRequiredMixin, FormMixin, DetailView):
|
||||||
form_class = ImageForm
|
form_class = ImageForm
|
||||||
@ -368,6 +326,17 @@ class ClubDetailView(LoginRequiredMixin, DetailView):
|
|||||||
context['member_list'] = club_member
|
context['member_list'] = club_member
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
class ClubAliasView(LoginRequiredMixin, DetailView):
|
||||||
|
model = Club
|
||||||
|
template_name = 'member/club_alias.html'
|
||||||
|
context_object_name = 'club'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
note = context['object'].note
|
||||||
|
context["aliases"] = AliasTable(note.alias_set.all())
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ClubUpdateView(LoginRequiredMixin, UpdateView):
|
class ClubUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
model = Club
|
model = Club
|
||||||
@ -395,12 +364,12 @@ class ClubAddMemberView(LoginRequiredMixin, CreateView):
|
|||||||
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")
|
return super().get_queryset().filter(PermissionBackend.filter_queryset(self.request.user, Membership, "view")
|
||||||
| PermissionBackend.filter_queryset(self.request.user, Membership,
|
| PermissionBackend.filter_queryset(self.request.user, Membership,
|
||||||
"change"))
|
"change"))
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
club = Club.objects.get(pk=self.kwargs["pk"])
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['formset'] = MemberFormSet()
|
context['formset'] = MemberFormSet()
|
||||||
context['helper'] = FormSetHelper()
|
context['helper'] = FormSetHelper()
|
||||||
|
context['club'] = club
|
||||||
context['no_cache'] = True
|
context['no_cache'] = True
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
@ -78,7 +78,11 @@ class AliasSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Alias
|
model = Alias
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ('note', )
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
instance = Alias(**attrs)
|
||||||
|
instance.clean()
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class NotePolymorphicSerializer(PolymorphicSerializer):
|
class NotePolymorphicSerializer(PolymorphicSerializer):
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet
|
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSet
|
||||||
|
|
||||||
from .serializers import NotePolymorphicSerializer, AliasSerializer, TemplateCategorySerializer, \
|
from .serializers import NotePolymorphicSerializer, AliasSerializer, TemplateCategorySerializer, \
|
||||||
TransactionTemplateSerializer, TransactionPolymorphicSerializer
|
TransactionTemplateSerializer, TransactionPolymorphicSerializer
|
||||||
@ -53,6 +57,22 @@ class AliasViewSet(ReadProtectedModelViewSet):
|
|||||||
search_fields = ['$normalized_name', '$name', '$note__polymorphic_ctype__model', ]
|
search_fields = ['$normalized_name', '$name', '$note__polymorphic_ctype__model', ]
|
||||||
ordering_fields = ['name', 'normalized_name']
|
ordering_fields = ['name', 'normalized_name']
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
serializer_class = self.serializer_class
|
||||||
|
if self.request.method in ['PUT', 'PATCH']:
|
||||||
|
#alias owner cannot be change once establish
|
||||||
|
setattr(serializer_class.Meta, 'read_only_fields', ('note',))
|
||||||
|
return serializer_class
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
try:
|
||||||
|
self.perform_destroy(instance)
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e)
|
||||||
|
return Response({e.code:e.message},status.HTTP_400_BAD_REQUEST)
|
||||||
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""
|
"""
|
||||||
Parse query and apply filters.
|
Parse query and apply filters.
|
||||||
|
58
apps/note/fixtures/button.json
Normal file
58
apps/note/fixtures/button.json
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"name": "Soft"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 2,
|
||||||
|
"fields": {
|
||||||
|
"name": "Pulls"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 3,
|
||||||
|
"fields": {
|
||||||
|
"name": "Gala"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 4,
|
||||||
|
"fields": {
|
||||||
|
"name": "Clubs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 5,
|
||||||
|
"fields": {
|
||||||
|
"name": "Bouffe"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 6,
|
||||||
|
"fields": {
|
||||||
|
"name": "BDA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 7,
|
||||||
|
"fields": {
|
||||||
|
"name": "Autre"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "note.templatecategory",
|
||||||
|
"pk": 8,
|
||||||
|
"fields": {
|
||||||
|
"name": "Alcool"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -184,61 +184,5 @@
|
|||||||
"normalized_name": "kfet",
|
"normalized_name": "kfet",
|
||||||
"note": 6
|
"note": 6
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 1,
|
|
||||||
"fields": {
|
|
||||||
"name": "Soft"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 2,
|
|
||||||
"fields": {
|
|
||||||
"name": "Pulls"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 3,
|
|
||||||
"fields": {
|
|
||||||
"name": "Gala"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 4,
|
|
||||||
"fields": {
|
|
||||||
"name": "Clubs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 5,
|
|
||||||
"fields": {
|
|
||||||
"name": "Bouffe"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 6,
|
|
||||||
"fields": {
|
|
||||||
"name": "BDA"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 7,
|
|
||||||
"fields": {
|
|
||||||
"name": "Autre"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "note.templatecategory",
|
|
||||||
"pk": 8,
|
|
||||||
"fields": {
|
|
||||||
"name": "Alcool"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -9,17 +9,6 @@ from .models import Alias
|
|||||||
from .models import TransactionTemplate
|
from .models import TransactionTemplate
|
||||||
|
|
||||||
|
|
||||||
class AliasForm(forms.ModelForm):
|
|
||||||
class Meta:
|
|
||||||
model = Alias
|
|
||||||
fields = ("name",)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.fields["name"].label = False
|
|
||||||
self.fields["name"].widget.attrs = {"placeholder": _('New Alias')}
|
|
||||||
|
|
||||||
|
|
||||||
class ImageForm(forms.Form):
|
class ImageForm(forms.Form):
|
||||||
image = forms.ImageField(required=False,
|
image = forms.ImageField(required=False,
|
||||||
label=_('select an image'),
|
label=_('select an image'),
|
||||||
|
@ -228,7 +228,7 @@ class Alias(models.Model):
|
|||||||
for cat in {'M', 'P', 'Z', 'C'})).casefold()
|
for cat in {'M', 'P', 'Z', 'C'})).casefold()
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
normalized_name = Alias.normalize(self.name)
|
normalized_name = self.normalize(self.name)
|
||||||
if len(normalized_name) >= 255:
|
if len(normalized_name) >= 255:
|
||||||
raise ValidationError(_('Alias is too long.'),
|
raise ValidationError(_('Alias is too long.'),
|
||||||
code='alias_too_long')
|
code='alias_too_long')
|
||||||
@ -242,8 +242,12 @@ class Alias(models.Model):
|
|||||||
pass
|
pass
|
||||||
self.normalized_name = normalized_name
|
self.normalized_name = normalized_name
|
||||||
|
|
||||||
|
def save(self,*args,**kwargs):
|
||||||
|
self.normalized_name = self.normalize(self.name)
|
||||||
|
super().save(*args,**kwargs)
|
||||||
|
|
||||||
def delete(self, using=None, keep_parents=False):
|
def delete(self, using=None, keep_parents=False):
|
||||||
if self.name == str(self.note):
|
if self.name == str(self.note):
|
||||||
raise ValidationError(_("You can't delete your main alias."),
|
raise ValidationError(_("You can't delete your main alias."),
|
||||||
code="cant_delete_main_alias")
|
code="main_alias")
|
||||||
return super().delete(using, keep_parents)
|
return super().delete(using, keep_parents)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import F
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
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 _
|
||||||
@ -93,12 +94,26 @@ class Transaction(PolymorphicModel):
|
|||||||
related_name='+',
|
related_name='+',
|
||||||
verbose_name=_('source'),
|
verbose_name=_('source'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
source_alias = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
default="", # Will be remplaced by the name of the note on save
|
||||||
|
verbose_name=_('used alias'),
|
||||||
|
)
|
||||||
|
|
||||||
destination = models.ForeignKey(
|
destination = models.ForeignKey(
|
||||||
Note,
|
Note,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='+',
|
related_name='+',
|
||||||
verbose_name=_('destination'),
|
verbose_name=_('destination'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
destination_alias = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
default="", # Will be remplaced by the name of the note on save
|
||||||
|
verbose_name=_('used alias'),
|
||||||
|
)
|
||||||
|
|
||||||
created_at = models.DateTimeField(
|
created_at = models.DateTimeField(
|
||||||
verbose_name=_('created at'),
|
verbose_name=_('created at'),
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
@ -115,11 +130,19 @@ class Transaction(PolymorphicModel):
|
|||||||
verbose_name=_('reason'),
|
verbose_name=_('reason'),
|
||||||
max_length=255,
|
max_length=255,
|
||||||
)
|
)
|
||||||
|
|
||||||
valid = models.BooleanField(
|
valid = models.BooleanField(
|
||||||
verbose_name=_('valid'),
|
verbose_name=_('valid'),
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
invalidity_reason = models.CharField(
|
||||||
|
verbose_name=_('invalidity reason'),
|
||||||
|
max_length=255,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("transaction")
|
verbose_name = _("transaction")
|
||||||
verbose_name_plural = _("transactions")
|
verbose_name_plural = _("transactions")
|
||||||
@ -134,6 +157,13 @@ class Transaction(PolymorphicModel):
|
|||||||
When saving, also transfer money between two notes
|
When saving, also transfer money between two notes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# If the aliases are not entered, we assume that the used alias is the name of the note
|
||||||
|
if not self.source_alias:
|
||||||
|
self.source_alias = str(self.source)
|
||||||
|
|
||||||
|
if not self.destination_alias:
|
||||||
|
self.destination_alias = str(self.destination)
|
||||||
|
|
||||||
if self.source.pk == self.destination.pk:
|
if self.source.pk == self.destination.pk:
|
||||||
# When source == destination, no money is transfered
|
# When source == destination, no money is transfered
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
@ -152,6 +182,10 @@ class Transaction(PolymorphicModel):
|
|||||||
self.source.balance -= to_transfer
|
self.source.balance -= to_transfer
|
||||||
self.destination.balance += to_transfer
|
self.destination.balance += to_transfer
|
||||||
|
|
||||||
|
# When a transaction is declared valid, we ensure that the invalidity reason is null, if it was
|
||||||
|
# previously invalid
|
||||||
|
self.invalidity_reason = None
|
||||||
|
|
||||||
# We save first the transaction, in case of the user has no right to transfer money
|
# We save first the transaction, in case of the user has no right to transfer money
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import html
|
|||||||
|
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
from django.utils.html import format_html
|
||||||
from django_tables2.utils import A
|
from django_tables2.utils import A
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
@ -20,19 +21,48 @@ class HistoryTable(tables.Table):
|
|||||||
'table table-condensed table-striped table-hover'
|
'table table-condensed table-striped table-hover'
|
||||||
}
|
}
|
||||||
model = Transaction
|
model = Transaction
|
||||||
exclude = ("id", "polymorphic_ctype", )
|
exclude = ("id", "polymorphic_ctype", "invalidity_reason", "source_alias", "destination_alias",)
|
||||||
template_name = 'django_tables2/bootstrap4.html'
|
template_name = 'django_tables2/bootstrap4.html'
|
||||||
sequence = ('...', 'type', 'total', 'valid', )
|
sequence = ('...', 'type', 'total', 'valid',)
|
||||||
orderable = False
|
orderable = False
|
||||||
|
|
||||||
|
source = tables.Column(
|
||||||
|
attrs={
|
||||||
|
"td": {
|
||||||
|
"data-toggle": "tooltip",
|
||||||
|
"title": lambda record: _("used alias").capitalize() + " : " + record.source_alias,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
destination = tables.Column(
|
||||||
|
attrs={
|
||||||
|
"td": {
|
||||||
|
"data-toggle": "tooltip",
|
||||||
|
"title": lambda record: _("used alias").capitalize() + " : " + record.destination_alias,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
type = tables.Column()
|
type = tables.Column()
|
||||||
|
|
||||||
total = tables.Column() # will use Transaction.total() !!
|
total = tables.Column() # will use Transaction.total() !!
|
||||||
|
|
||||||
valid = tables.Column(attrs={"td": {"id": lambda record: "validate_" + str(record.id),
|
valid = tables.Column(
|
||||||
"class": lambda record: str(record.valid).lower() + ' validate',
|
attrs={
|
||||||
"onclick": lambda record: 'de_validate(' + str(record.id) + ', '
|
"td": {
|
||||||
+ str(record.valid).lower() + ')'}})
|
"id": lambda record: "validate_" + str(record.id),
|
||||||
|
"class": lambda record: str(record.valid).lower() + ' validate',
|
||||||
|
"data-toggle": "tooltip",
|
||||||
|
"title": lambda record: _("Click to invalidate") if record.valid else _("Click to validate"),
|
||||||
|
"onclick": lambda record: 'in_validate(' + str(record.id) + ', ' + str(record.valid).lower() + ')',
|
||||||
|
"onmouseover": lambda record: '$("#invalidity_reason_'
|
||||||
|
+ str(record.id) + '").show();$("#invalidity_reason_'
|
||||||
|
+ str(record.id) + '").focus();',
|
||||||
|
"onmouseout": lambda record: '$("#invalidity_reason_' + str(record.id) + '").hide()',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def order_total(self, queryset, is_descending):
|
def order_total(self, queryset, is_descending):
|
||||||
# needed for rendering
|
# needed for rendering
|
||||||
@ -53,13 +83,23 @@ class HistoryTable(tables.Table):
|
|||||||
def render_reason(self, value):
|
def render_reason(self, value):
|
||||||
return html.unescape(value)
|
return html.unescape(value)
|
||||||
|
|
||||||
def render_valid(self, value):
|
def render_valid(self, value, record):
|
||||||
return "✔" if value else "✖"
|
"""
|
||||||
|
When the validation status is hovered, an input field is displayed to let the user specify an invalidity reason
|
||||||
|
"""
|
||||||
|
val = "✔" if value else "✖"
|
||||||
|
val += "<input type='text' class='form-control' id='invalidity_reason_" + str(record.id) \
|
||||||
|
+ "' value='" + (html.escape(record.invalidity_reason)
|
||||||
|
if record.invalidity_reason else ("" if value else str(_("No reason specified")))) \
|
||||||
|
+ "'" + ("" if value else " disabled") \
|
||||||
|
+ " placeholder='" + html.escape(_("invalidity reason").capitalize()) + "'" \
|
||||||
|
+ " style='position: absolute; width: 15em; margin-left: -15.5em; margin-top: -2em; display: none;'>"
|
||||||
|
return format_html(val)
|
||||||
|
|
||||||
|
|
||||||
# function delete_button(id) provided in template file
|
# function delete_button(id) provided in template file
|
||||||
DELETE_TEMPLATE = """
|
DELETE_TEMPLATE = """
|
||||||
<button id="{{ record.pk }}" class="btn btn-danger" onclick="delete_button(this.id)"> {{ delete_trans }}</button>
|
<button id="{{ record.pk }}" class="btn btn-danger btn-sm" onclick="delete_button(this.id)"> {{ delete_trans }}</button>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +107,8 @@ class AliasTable(tables.Table):
|
|||||||
class Meta:
|
class Meta:
|
||||||
attrs = {
|
attrs = {
|
||||||
'class':
|
'class':
|
||||||
'table table condensed table-striped table-hover'
|
'table table condensed table-striped table-hover',
|
||||||
|
'id':"alias_table"
|
||||||
}
|
}
|
||||||
model = Alias
|
model = Alias
|
||||||
fields = ('name',)
|
fields = ('name',)
|
||||||
@ -75,15 +116,11 @@ class AliasTable(tables.Table):
|
|||||||
|
|
||||||
show_header = False
|
show_header = False
|
||||||
name = tables.Column(attrs={'td': {'class': 'text-center'}})
|
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',
|
delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
|
||||||
args=[A('pk')],
|
extra_context={"delete_trans": _('delete')},
|
||||||
attrs={
|
attrs={'td': {'class': 'col-sm-1'}})
|
||||||
'td': {'class': 'col-sm-2'},
|
|
||||||
'a': {'class': 'btn btn-danger'}},
|
|
||||||
text='delete', accessor='pk')
|
|
||||||
|
|
||||||
|
|
||||||
class ButtonTable(tables.Table):
|
class ButtonTable(tables.Table):
|
||||||
@ -103,11 +140,11 @@ class ButtonTable(tables.Table):
|
|||||||
edit = tables.LinkColumn('note:template_update',
|
edit = tables.LinkColumn('note:template_update',
|
||||||
args=[A('pk')],
|
args=[A('pk')],
|
||||||
attrs={'td': {'class': 'col-sm-1'},
|
attrs={'td': {'class': 'col-sm-1'},
|
||||||
'a': {'class': 'btn btn-primary'}},
|
'a': {'class': 'btn btn-sm btn-primary'}},
|
||||||
text=_('edit'),
|
text=_('edit'),
|
||||||
accessor='pk')
|
accessor='pk')
|
||||||
|
|
||||||
delete = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
|
delete_col = tables.TemplateColumn(template_code=DELETE_TEMPLATE,
|
||||||
extra_context={"delete_trans": _('delete')},
|
extra_context={"delete_trans": _('delete')},
|
||||||
attrs={'td': {'class': 'col-sm-1'}})
|
attrs={'td': {'class': 'col-sm-1'}})
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@
|
|||||||
"note",
|
"note",
|
||||||
"transaction"
|
"transaction"
|
||||||
],
|
],
|
||||||
"query": "[\"AND\", {\"source\": [\"user\", \"note\"]}, {\"amount__lte\": [\"user\", \"note\", \"balance\"]}]",
|
"query": "[\"AND\", {\"source\": [\"user\", \"note\"]}, [\"OR\", {\"amount__lte\": [\"user\", \"note\", \"balance\"]}, {\"valid\": false}]]",
|
||||||
"type": "add",
|
"type": "add",
|
||||||
"mask": 1,
|
"mask": 1,
|
||||||
"field": "",
|
"field": "",
|
||||||
@ -387,7 +387,7 @@
|
|||||||
"note",
|
"note",
|
||||||
"recurrenttransaction"
|
"recurrenttransaction"
|
||||||
],
|
],
|
||||||
"query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, {\"amount__lte\": {\"F\": [\"ADD\", [\"F\", \"source__balance\"], 5000]}}]",
|
"query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, [\"OR\", {\"amount__lte\": {\"F\": [\"ADD\", [\"F\", \"source__balance\"], 5000]}}, {\"valid\": false}]]",
|
||||||
"type": "add",
|
"type": "add",
|
||||||
"mask": 2,
|
"mask": 2,
|
||||||
"field": "",
|
"field": "",
|
||||||
|
@ -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-03-24 15:49+0100\n"
|
"POT-Creation-Date: 2020-03-26 14:40+0100\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"
|
||||||
@ -24,8 +24,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: apps/activity/models.py:19 apps/activity/models.py:44
|
#: apps/activity/models.py:19 apps/activity/models.py:44
|
||||||
#: apps/member/models.py:63 apps/member/models.py:114
|
#: apps/member/models.py:63 apps/member/models.py:114
|
||||||
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
|
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25
|
||||||
#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:198
|
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:232
|
||||||
#: templates/member/profile_detail.html:15
|
#: templates/member/profile_detail.html:15
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -46,13 +46,13 @@ msgstr ""
|
|||||||
msgid "activity types"
|
msgid "activity types"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/activity/models.py:48 apps/note/models/transactions.py:69
|
#: apps/activity/models.py:48 apps/note/models/transactions.py:70
|
||||||
#: apps/permission/models.py:90
|
#: apps/permission/models.py:91
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/activity/models.py:54 apps/note/models/notes.py:164
|
#: apps/activity/models.py:54 apps/note/models/notes.py:164
|
||||||
#: apps/note/models/transactions.py:62
|
#: apps/note/models/transactions.py:63
|
||||||
msgid "type"
|
msgid "type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -120,11 +120,11 @@ msgstr ""
|
|||||||
msgid "create"
|
msgid "create"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/logs/models.py:61
|
#: apps/logs/models.py:61 apps/note/tables.py:147
|
||||||
msgid "edit"
|
msgid "edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/logs/models.py:62
|
#: apps/logs/models.py:62 apps/note/tables.py:151
|
||||||
msgid "delete"
|
msgid "delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ msgstr ""
|
|||||||
msgid "clubs"
|
msgid "clubs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/member/models.py:120 apps/permission/models.py:275
|
#: apps/member/models.py:120 apps/permission/models.py:276
|
||||||
msgid "role"
|
msgid "role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -255,12 +255,12 @@ msgstr ""
|
|||||||
msgid "Alias successfully deleted"
|
msgid "Alias successfully deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/admin.py:120 apps/note/models/transactions.py:94
|
#: apps/note/admin.py:120 apps/note/models/transactions.py:95
|
||||||
msgid "source"
|
msgid "source"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/admin.py:128 apps/note/admin.py:156
|
#: apps/note/admin.py:128 apps/note/admin.py:156
|
||||||
#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:100
|
#: apps/note/models/transactions.py:54 apps/note/models/transactions.py:108
|
||||||
msgid "destination"
|
msgid "destination"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ msgstr ""
|
|||||||
msgid "display image"
|
msgid "display image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:103
|
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:118
|
||||||
msgid "created at"
|
msgid "created at"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -384,55 +384,64 @@ msgstr ""
|
|||||||
msgid "You can't delete your main alias."
|
msgid "You can't delete your main alias."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:30
|
#: apps/note/models/transactions.py:31
|
||||||
msgid "transaction category"
|
msgid "transaction category"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:31
|
#: apps/note/models/transactions.py:32
|
||||||
msgid "transaction categories"
|
msgid "transaction categories"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:47
|
#: apps/note/models/transactions.py:48
|
||||||
msgid "A template with this name already exist"
|
msgid "A template with this name already exist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:111
|
#: apps/note/models/transactions.py:57 apps/note/models/transactions.py:126
|
||||||
msgid "amount"
|
msgid "amount"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:57
|
#: apps/note/models/transactions.py:58
|
||||||
msgid "in centimes"
|
msgid "in centimes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:75
|
#: apps/note/models/transactions.py:76
|
||||||
msgid "transaction template"
|
msgid "transaction template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:76
|
#: apps/note/models/transactions.py:77
|
||||||
msgid "transaction templates"
|
msgid "transaction templates"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:107
|
#: apps/note/models/transactions.py:101 apps/note/models/transactions.py:114
|
||||||
|
#: apps/note/tables.py:33 apps/note/tables.py:42
|
||||||
|
msgid "used alias"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: apps/note/models/transactions.py:122
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:115
|
#: apps/note/models/transactions.py:130
|
||||||
msgid "reason"
|
msgid "reason"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:119
|
#: apps/note/models/transactions.py:135
|
||||||
msgid "valid"
|
msgid "valid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:124
|
#: apps/note/models/transactions.py:140 apps/note/tables.py:95
|
||||||
|
msgid "invalidity reason"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: apps/note/models/transactions.py:147
|
||||||
msgid "transaction"
|
msgid "transaction"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:125
|
#: apps/note/models/transactions.py:148
|
||||||
msgid "transactions"
|
msgid "transactions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:168 templates/base.html:98
|
#: apps/note/models/transactions.py:202 templates/base.html:83
|
||||||
#: templates/note/transaction_form.html:19
|
#: templates/note/transaction_form.html:19
|
||||||
#: templates/note/transaction_form.html:145
|
#: templates/note/transaction_form.html:145
|
||||||
msgid "Transfer"
|
msgid "Transfer"
|
||||||
@ -634,15 +643,15 @@ msgid ""
|
|||||||
"again unless your session expires or you logout."
|
"again unless your session expires or you logout."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:153
|
#: note_kfet/settings/base.py:151
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:154
|
#: note_kfet/settings/base.py:152
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:155
|
#: note_kfet/settings/base.py:153
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -650,18 +659,14 @@ msgstr ""
|
|||||||
msgid "The ENS Paris-Saclay BDE note."
|
msgid "The ENS Paris-Saclay BDE note."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/base.html:84
|
#: templates/base.html:87
|
||||||
msgid "Clubs"
|
msgid "Clubs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/base.html:89
|
#: templates/base.html:92
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/base.html:94
|
|
||||||
msgid "Buttons"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/cas_server/base.html:7
|
#: templates/cas_server/base.html:7
|
||||||
msgid "Central Authentication Service"
|
msgid "Central Authentication Service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -798,7 +803,7 @@ msgstr ""
|
|||||||
msgid "Sign up"
|
msgid "Sign up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/note/conso_form.html:28 templates/note/transaction_form.html:40
|
#: templates/note/conso_form.html:28 templates/note/transaction_form.html:50
|
||||||
msgid "Select emitters"
|
msgid "Select emitters"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -842,12 +847,28 @@ msgstr ""
|
|||||||
msgid "Transfer type"
|
msgid "Transfer type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:86
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:92
|
||||||
|
msgid "First name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:98
|
||||||
|
msgid "Bank"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: templates/note/transaction_form.html:111
|
#: templates/note/transaction_form.html:111
|
||||||
#: templates/note/transaction_form.html:169
|
#: templates/note/transaction_form.html:169
|
||||||
#: templates/note/transaction_form.html:176
|
#: templates/note/transaction_form.html:176
|
||||||
msgid "Select receivers"
|
msgid "Select receivers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:128
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: templates/note/transaction_form.html:138
|
#: templates/note/transaction_form.html:138
|
||||||
msgid "Reason"
|
msgid "Reason"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -864,6 +885,22 @@ msgstr ""
|
|||||||
msgid "Buttons list"
|
msgid "Buttons list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:9
|
||||||
|
msgid "search button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:20
|
||||||
|
msgid "buttons listing "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:71
|
||||||
|
msgid "button successfully deleted "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:75
|
||||||
|
msgid "Unable to delete button "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: templates/registration/logged_out.html:8
|
#: templates/registration/logged_out.html:8
|
||||||
msgid "Thanks for spending some quality time with the Web site today."
|
msgid "Thanks for spending some quality time with the Web site today."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -873,7 +910,7 @@ msgid "Log in again"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/registration/login.html:7 templates/registration/login.html:8
|
#: templates/registration/login.html:7 templates/registration/login.html:8
|
||||||
#: templates/registration/login.html:26
|
#: templates/registration/login.html:28
|
||||||
#: templates/registration/password_reset_complete.html:10
|
#: templates/registration/password_reset_complete.html:10
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -885,7 +922,15 @@ msgid ""
|
|||||||
"page. Would you like to login to a different account?"
|
"page. Would you like to login to a different account?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/registration/login.html:27
|
#: templates/registration/login.html:22
|
||||||
|
msgid "You can also register via the central authentification server "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/registration/login.html:23
|
||||||
|
msgid "using this link "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/registration/login.html:29
|
||||||
msgid "Forgotten your password or username?"
|
msgid "Forgotten your password or username?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3,7 +3,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-03-24 15:49+0100\n"
|
"POT-Creation-Date: 2020-03-26 14:40+0100\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"
|
||||||
@ -19,8 +19,8 @@ msgstr "activité"
|
|||||||
|
|
||||||
#: apps/activity/models.py:19 apps/activity/models.py:44
|
#: apps/activity/models.py:19 apps/activity/models.py:44
|
||||||
#: apps/member/models.py:63 apps/member/models.py:114
|
#: apps/member/models.py:63 apps/member/models.py:114
|
||||||
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
|
#: apps/note/models/notes.py:188 apps/note/models/transactions.py:25
|
||||||
#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:198
|
#: apps/note/models/transactions.py:45 apps/note/models/transactions.py:232
|
||||||
#: templates/member/profile_detail.html:15
|
#: templates/member/profile_detail.html:15
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nom"
|
msgstr "nom"
|
||||||
@ -41,13 +41,13 @@ msgstr "type d'activité"
|
|||||||
msgid "activity types"
|
msgid "activity types"
|
||||||
msgstr "types d'activité"
|
msgstr "types d'activité"
|
||||||
|
|
||||||
#: apps/activity/models.py:48 apps/note/models/transactions.py:69
|
#: apps/activity/models.py:48 apps/note/models/transactions.py:70
|
||||||
#: apps/permission/models.py:90
|
#: apps/permission/models.py:91
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr "description"
|
msgstr "description"
|
||||||
|
|
||||||
#: apps/activity/models.py:54 apps/note/models/notes.py:164
|
#: apps/activity/models.py:54 apps/note/models/notes.py:164
|
||||||
#: apps/note/models/transactions.py:62
|
#: apps/note/models/transactions.py:63
|
||||||
msgid "type"
|
msgid "type"
|
||||||
msgstr "type"
|
msgstr "type"
|
||||||
|
|
||||||
@ -115,11 +115,11 @@ msgstr "Nouvelles données"
|
|||||||
msgid "create"
|
msgid "create"
|
||||||
msgstr "Créer"
|
msgstr "Créer"
|
||||||
|
|
||||||
#: apps/logs/models.py:61
|
#: apps/logs/models.py:61 apps/note/tables.py:147
|
||||||
msgid "edit"
|
msgid "edit"
|
||||||
msgstr "Modifier"
|
msgstr "Modifier"
|
||||||
|
|
||||||
#: apps/logs/models.py:62
|
#: apps/logs/models.py:62 apps/note/tables.py:151
|
||||||
msgid "delete"
|
msgid "delete"
|
||||||
msgstr "Supprimer"
|
msgstr "Supprimer"
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ msgstr "club"
|
|||||||
msgid "clubs"
|
msgid "clubs"
|
||||||
msgstr "clubs"
|
msgstr "clubs"
|
||||||
|
|
||||||
#: apps/member/models.py:120 apps/permission/models.py:275
|
#: apps/member/models.py:120 apps/permission/models.py:276
|
||||||
msgid "role"
|
msgid "role"
|
||||||
msgstr "rôle"
|
msgstr "rôle"
|
||||||
|
|
||||||
@ -254,12 +254,12 @@ msgstr "Compte n°%(id)s : %(username)s"
|
|||||||
msgid "Alias successfully deleted"
|
msgid "Alias successfully deleted"
|
||||||
msgstr "L'alias a bien été supprimé"
|
msgstr "L'alias a bien été supprimé"
|
||||||
|
|
||||||
#: apps/note/admin.py:120 apps/note/models/transactions.py:94
|
#: apps/note/admin.py:120 apps/note/models/transactions.py:95
|
||||||
msgid "source"
|
msgid "source"
|
||||||
msgstr "source"
|
msgstr "source"
|
||||||
|
|
||||||
#: apps/note/admin.py:128 apps/note/admin.py:156
|
#: apps/note/admin.py:128 apps/note/admin.py:156
|
||||||
#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:100
|
#: apps/note/models/transactions.py:54 apps/note/models/transactions.py:108
|
||||||
msgid "destination"
|
msgid "destination"
|
||||||
msgstr "destination"
|
msgstr "destination"
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ msgstr ""
|
|||||||
msgid "display image"
|
msgid "display image"
|
||||||
msgstr "image affichée"
|
msgstr "image affichée"
|
||||||
|
|
||||||
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:103
|
#: apps/note/models/notes.py:53 apps/note/models/transactions.py:118
|
||||||
msgid "created at"
|
msgid "created at"
|
||||||
msgstr "créée le"
|
msgstr "créée le"
|
||||||
|
|
||||||
@ -384,35 +384,40 @@ msgstr "Un alias avec un nom similaire existe déjà : {}"
|
|||||||
msgid "You can't delete your main alias."
|
msgid "You can't delete your main alias."
|
||||||
msgstr "Vous ne pouvez pas supprimer votre alias principal."
|
msgstr "Vous ne pouvez pas supprimer votre alias principal."
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:30
|
#: apps/note/models/transactions.py:31
|
||||||
msgid "transaction category"
|
msgid "transaction category"
|
||||||
msgstr "catégorie de transaction"
|
msgstr "catégorie de transaction"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:31
|
#: apps/note/models/transactions.py:32
|
||||||
msgid "transaction categories"
|
msgid "transaction categories"
|
||||||
msgstr "catégories de transaction"
|
msgstr "catégories de transaction"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:47
|
#: apps/note/models/transactions.py:48
|
||||||
msgid "A template with this name already exist"
|
msgid "A template with this name already exist"
|
||||||
msgstr "Un modèle de transaction avec un nom similaire existe déjà."
|
msgstr "Un modèle de transaction avec un nom similaire existe déjà."
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:111
|
#: apps/note/models/transactions.py:57 apps/note/models/transactions.py:126
|
||||||
msgid "amount"
|
msgid "amount"
|
||||||
msgstr "montant"
|
msgstr "montant"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:57
|
#: apps/note/models/transactions.py:58
|
||||||
msgid "in centimes"
|
msgid "in centimes"
|
||||||
msgstr "en centimes"
|
msgstr "en centimes"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:75
|
#: apps/note/models/transactions.py:76
|
||||||
msgid "transaction template"
|
msgid "transaction template"
|
||||||
msgstr "modèle de transaction"
|
msgstr "modèle de transaction"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:76
|
#: apps/note/models/transactions.py:77
|
||||||
msgid "transaction templates"
|
msgid "transaction templates"
|
||||||
msgstr "modèles de transaction"
|
msgstr "modèles de transaction"
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:107
|
#: apps/note/models/transactions.py:101 apps/note/models/transactions.py:114
|
||||||
|
#: apps/note/tables.py:33 apps/note/tables.py:42
|
||||||
|
msgid "used alias"
|
||||||
|
msgstr "alias utilisé"
|
||||||
|
|
||||||
|
#: apps/note/models/transactions.py:122
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr "quantité"
|
msgstr "quantité"
|
||||||
|
|
||||||
@ -634,15 +639,15 @@ msgid ""
|
|||||||
"again unless your session expires or you logout."
|
"again unless your session expires or you logout."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:153
|
#: note_kfet/settings/base.py:151
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:154
|
#: note_kfet/settings/base.py:152
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: note_kfet/settings/base.py:155
|
#: note_kfet/settings/base.py:153
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -650,18 +655,14 @@ msgstr ""
|
|||||||
msgid "The ENS Paris-Saclay BDE note."
|
msgid "The ENS Paris-Saclay BDE note."
|
||||||
msgstr "La note du BDE de l'ENS Paris-Saclay."
|
msgstr "La note du BDE de l'ENS Paris-Saclay."
|
||||||
|
|
||||||
#: templates/base.html:84
|
#: templates/base.html:87
|
||||||
msgid "Clubs"
|
msgid "Clubs"
|
||||||
msgstr "Clubs"
|
msgstr "Clubs"
|
||||||
|
|
||||||
#: templates/base.html:89
|
#: templates/base.html:92
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Activités"
|
msgstr "Activités"
|
||||||
|
|
||||||
#: templates/base.html:94
|
|
||||||
msgid "Buttons"
|
|
||||||
msgstr "Boutons"
|
|
||||||
|
|
||||||
#: templates/cas_server/base.html:7
|
#: templates/cas_server/base.html:7
|
||||||
msgid "Central Authentication Service"
|
msgid "Central Authentication Service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -800,7 +801,7 @@ msgstr "Sauvegarder les changements"
|
|||||||
msgid "Sign up"
|
msgid "Sign up"
|
||||||
msgstr "Inscription"
|
msgstr "Inscription"
|
||||||
|
|
||||||
#: templates/note/conso_form.html:28 templates/note/transaction_form.html:40
|
#: templates/note/conso_form.html:28 templates/note/transaction_form.html:50
|
||||||
msgid "Select emitters"
|
msgid "Select emitters"
|
||||||
msgstr "Sélection des émetteurs"
|
msgstr "Sélection des émetteurs"
|
||||||
|
|
||||||
@ -844,12 +845,28 @@ msgstr "Paiement externe"
|
|||||||
msgid "Transfer type"
|
msgid "Transfer type"
|
||||||
msgstr "Type de transfert"
|
msgstr "Type de transfert"
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:86
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:92
|
||||||
|
msgid "First name"
|
||||||
|
msgstr "Prénom"
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:98
|
||||||
|
msgid "Bank"
|
||||||
|
msgstr "Banque"
|
||||||
|
|
||||||
#: templates/note/transaction_form.html:111
|
#: templates/note/transaction_form.html:111
|
||||||
#: templates/note/transaction_form.html:169
|
#: templates/note/transaction_form.html:169
|
||||||
#: templates/note/transaction_form.html:176
|
#: templates/note/transaction_form.html:176
|
||||||
msgid "Select receivers"
|
msgid "Select receivers"
|
||||||
msgstr "Sélection des destinataires"
|
msgstr "Sélection des destinataires"
|
||||||
|
|
||||||
|
#: templates/note/transaction_form.html:128
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr "Montant"
|
||||||
|
|
||||||
#: templates/note/transaction_form.html:138
|
#: templates/note/transaction_form.html:138
|
||||||
msgid "Reason"
|
msgid "Reason"
|
||||||
msgstr "Raison"
|
msgstr "Raison"
|
||||||
@ -866,6 +883,22 @@ msgstr "Note à débiter"
|
|||||||
msgid "Buttons list"
|
msgid "Buttons list"
|
||||||
msgstr "Liste des boutons"
|
msgstr "Liste des boutons"
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:9
|
||||||
|
msgid "search button"
|
||||||
|
msgstr "Chercher un bouton"
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:20
|
||||||
|
msgid "buttons listing "
|
||||||
|
msgstr "Liste des boutons"
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:71
|
||||||
|
msgid "button successfully deleted "
|
||||||
|
msgstr "Le bouton a bien été supprimé"
|
||||||
|
|
||||||
|
#: templates/note/transactiontemplate_list.html:75
|
||||||
|
msgid "Unable to delete button "
|
||||||
|
msgstr "Impossible de supprimer le bouton "
|
||||||
|
|
||||||
#: templates/registration/logged_out.html:8
|
#: templates/registration/logged_out.html:8
|
||||||
msgid "Thanks for spending some quality time with the Web site today."
|
msgid "Thanks for spending some quality time with the Web site today."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -875,7 +908,7 @@ msgid "Log in again"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/registration/login.html:7 templates/registration/login.html:8
|
#: templates/registration/login.html:7 templates/registration/login.html:8
|
||||||
#: templates/registration/login.html:26
|
#: templates/registration/login.html:28
|
||||||
#: templates/registration/password_reset_complete.html:10
|
#: templates/registration/password_reset_complete.html:10
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -887,7 +920,15 @@ msgid ""
|
|||||||
"page. Would you like to login to a different account?"
|
"page. Would you like to login to a different account?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/registration/login.html:27
|
#: templates/registration/login.html:22
|
||||||
|
msgid "You can also register via the central authentification server "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/registration/login.html:23
|
||||||
|
msgid "using this link "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/registration/login.html:29
|
||||||
msgid "Forgotten your password or username?"
|
msgid "Forgotten your password or username?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
37
static/js/alias.js
Normal file
37
static/js/alias.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
$("#alias_input").on('keypress',function(e) {
|
||||||
|
if(e.which == 13) {
|
||||||
|
$("#alias_submit").click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function create_alias(note_id){
|
||||||
|
$.post("/api/note/alias/",
|
||||||
|
{
|
||||||
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
|
"name": $("#alias_input").val(),
|
||||||
|
"note": note_id
|
||||||
|
}
|
||||||
|
).done(function(){
|
||||||
|
$("#alias_table").load(location.href+ " #alias_table");
|
||||||
|
addMsg("Alias ajouté","success");
|
||||||
|
})
|
||||||
|
.fail(function(xhr, textStatus, error){
|
||||||
|
errMsg(xhr.responseJSON);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// on click of button "delete" , call the API
|
||||||
|
function delete_button(button_id){
|
||||||
|
$.ajax({
|
||||||
|
url:"/api/note/alias/"+button_id+"/",
|
||||||
|
method:"DELETE",
|
||||||
|
headers: {"X-CSRFTOKEN": CSRF_TOKEN}
|
||||||
|
})
|
||||||
|
.done(function(){
|
||||||
|
addMsg('Alias supprimé','success');
|
||||||
|
$("#alias_table").load(location.href + " #alias_table");
|
||||||
|
})
|
||||||
|
.fail(function(xhr,textStatus, error){
|
||||||
|
errMsg(xhr.responseJSON);
|
||||||
|
});
|
||||||
|
}
|
@ -28,7 +28,15 @@ function addMsg(msg, alert_type) {
|
|||||||
+ msg + "</div>\n";
|
+ msg + "</div>\n";
|
||||||
msgDiv.html(html);
|
msgDiv.html(html);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* add Muliple error message from err_obj
|
||||||
|
* @param err_obj {error_code:erro_message}
|
||||||
|
*/
|
||||||
|
function errMsg(errs_obj){
|
||||||
|
for (const err_msg of Object.values(errs_obj)) {
|
||||||
|
addMsg(err_msg,'danger');
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Reload the balance of the user on the right top corner
|
* Reload the balance of the user on the right top corner
|
||||||
*/
|
*/
|
||||||
@ -265,7 +273,16 @@ function autoCompleteNote(field_id, alias_matched_id, note_list_id, notes, notes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When a validate button is clicked, we switch the validation status
|
// When a validate button is clicked, we switch the validation status
|
||||||
function de_validate(id, validated) {
|
function in_validate(id, validated) {
|
||||||
|
|
||||||
|
let invalidity_reason;
|
||||||
|
let reason_obj = $("#invalidity_reason_" + id);
|
||||||
|
|
||||||
|
if (validated)
|
||||||
|
invalidity_reason = reason_obj.val();
|
||||||
|
else
|
||||||
|
invalidity_reason = null;
|
||||||
|
|
||||||
$("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>");
|
$("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>");
|
||||||
|
|
||||||
// Perform a PATCH request to the API in order to update the transaction
|
// Perform a PATCH request to the API in order to update the transaction
|
||||||
@ -278,12 +295,13 @@ function de_validate(id, validated) {
|
|||||||
"X-CSRFTOKEN": CSRF_TOKEN
|
"X-CSRFTOKEN": CSRF_TOKEN
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
"resourcetype": "RecurrentTransaction",
|
resourcetype: "RecurrentTransaction",
|
||||||
valid: !validated
|
valid: !validated,
|
||||||
|
invalidity_reason: invalidity_reason,
|
||||||
},
|
},
|
||||||
success: function () {
|
success: function () {
|
||||||
// Refresh jQuery objects
|
// Refresh jQuery objects
|
||||||
$(".validate").click(de_validate);
|
$(".validate").click(in_validate);
|
||||||
|
|
||||||
refreshBalance();
|
refreshBalance();
|
||||||
// error if this method doesn't exist. Please define it.
|
// error if this method doesn't exist. Please define it.
|
||||||
|
@ -167,7 +167,7 @@ function reset() {
|
|||||||
function consumeAll() {
|
function consumeAll() {
|
||||||
notes_display.forEach(function(note_display) {
|
notes_display.forEach(function(note_display) {
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function(button) {
|
||||||
consume(note_display.id, button.dest, button.quantity * note_display.quantity, button.amount,
|
consume(note_display.id, note_display.name, button.dest, button.quantity * note_display.quantity, button.amount,
|
||||||
button.name + " (" + button.category_name + ")", button.type, button.category_id, button.id);
|
button.name + " (" + button.category_name + ")", button.type, button.category_id, button.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -176,6 +176,7 @@ function consumeAll() {
|
|||||||
/**
|
/**
|
||||||
* Create a new transaction from a button through the API.
|
* Create a new transaction from a button through the API.
|
||||||
* @param source The note that paid the item (type: int)
|
* @param source The note that paid the item (type: int)
|
||||||
|
* @param source_alias The alias used for the source (type: str)
|
||||||
* @param dest The note that sold the item (type: int)
|
* @param dest The note that sold the item (type: int)
|
||||||
* @param quantity The quantity sold (type: int)
|
* @param quantity The quantity sold (type: int)
|
||||||
* @param amount The price of one item, in cents (type: int)
|
* @param amount The price of one item, in cents (type: int)
|
||||||
@ -184,7 +185,7 @@ function consumeAll() {
|
|||||||
* @param category The category id of the button (type: int)
|
* @param category The category id of the button (type: int)
|
||||||
* @param template The button id (type: int)
|
* @param template The button id (type: int)
|
||||||
*/
|
*/
|
||||||
function consume(source, dest, quantity, amount, reason, type, category, template) {
|
function consume(source, source_alias, dest, quantity, amount, reason, type, category, template) {
|
||||||
$.post("/api/note/transaction/transaction/",
|
$.post("/api/note/transaction/transaction/",
|
||||||
{
|
{
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
@ -195,12 +196,32 @@ function consume(source, dest, quantity, amount, reason, type, category, templat
|
|||||||
"polymorphic_ctype": type,
|
"polymorphic_ctype": type,
|
||||||
"resourcetype": "RecurrentTransaction",
|
"resourcetype": "RecurrentTransaction",
|
||||||
"source": source,
|
"source": source,
|
||||||
|
"source_alias": source_alias,
|
||||||
"destination": dest,
|
"destination": dest,
|
||||||
"category": category,
|
"category": category,
|
||||||
"template": template
|
"template": template
|
||||||
}, reset).fail(function (e) {
|
}, reset).fail(function (e) {
|
||||||
reset();
|
$.post("/api/note/transaction/transaction/",
|
||||||
|
{
|
||||||
addMsg("Une erreur est survenue lors de la transaction : " + e.responseText, "danger");
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
|
"quantity": quantity,
|
||||||
|
"amount": amount,
|
||||||
|
"reason": reason,
|
||||||
|
"valid": false,
|
||||||
|
"invalidity_reason": "Solde insuffisant",
|
||||||
|
"polymorphic_ctype": type,
|
||||||
|
"resourcetype": "RecurrentTransaction",
|
||||||
|
"source": source,
|
||||||
|
"source_alias": source_alias,
|
||||||
|
"destination": dest,
|
||||||
|
"category": category,
|
||||||
|
"template": template
|
||||||
|
}).done(function() {
|
||||||
|
reset();
|
||||||
|
addMsg("La transaction n'a pas pu être validée pour cause de solde insuffisant.", "danger");
|
||||||
|
}).fail(function () {
|
||||||
|
reset();
|
||||||
|
errMsg(e.responseJSON);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -83,19 +83,41 @@ $("#transfer").click(function() {
|
|||||||
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
"resourcetype": "Transaction",
|
"resourcetype": "Transaction",
|
||||||
"source": user_id,
|
"source": user_id,
|
||||||
"destination": dest.id
|
"destination": dest.id,
|
||||||
}, function () {
|
"destination_alias": dest.name
|
||||||
|
}).done(function () {
|
||||||
addMsg("Le transfert de "
|
addMsg("Le transfert de "
|
||||||
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
|
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
|
||||||
+ " vers la note " + dest.name + " a été fait avec succès !", "success");
|
+ " vers la note " + dest.name + " a été fait avec succès !", "success");
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}).fail(function (err) {
|
}).fail(function () {
|
||||||
addMsg("Le transfert de "
|
$.post("/api/note/transaction/transaction/",
|
||||||
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
|
{
|
||||||
+ " vers la note " + dest.name + " a échoué : " + err.responseText, "danger");
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
|
"quantity": dest.quantity,
|
||||||
|
"amount": 100 * $("#amount").val(),
|
||||||
|
"reason": $("#reason").val(),
|
||||||
|
"valid": false,
|
||||||
|
"invalidity_reason": "Solde insuffisant",
|
||||||
|
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
|
"resourcetype": "Transaction",
|
||||||
|
"source": user_id,
|
||||||
|
"destination": dest.id,
|
||||||
|
"destination_alias": dest.name
|
||||||
|
}).done(function () {
|
||||||
|
addMsg("Le transfert de "
|
||||||
|
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
|
||||||
|
+ " vers la note " + dest.name + " a échoué : Solde insuffisant", "danger");
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
}).fail(function (err) {
|
||||||
|
addMsg("Le transfert de "
|
||||||
|
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
|
||||||
|
+ " vers la note " + dest.name + " a échoué : " + err.responseText, "danger");
|
||||||
|
|
||||||
|
reset();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -112,19 +134,43 @@ $("#transfer").click(function() {
|
|||||||
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
"resourcetype": "Transaction",
|
"resourcetype": "Transaction",
|
||||||
"source": source.id,
|
"source": source.id,
|
||||||
"destination": dest.id
|
"source_alias": source.name,
|
||||||
}, function () {
|
"destination": dest.id,
|
||||||
|
"destination_alias": dest.name
|
||||||
|
}).done(function () {
|
||||||
addMsg("Le transfert de "
|
addMsg("Le transfert de "
|
||||||
+ pretty_money(source.quantity * dest.quantity * 100 * $("#amount").val()) + " de la note " + source.name
|
+ pretty_money(source.quantity * dest.quantity * 100 * $("#amount").val()) + " de la note " + source.name
|
||||||
+ " vers la note " + dest.name + " a été fait avec succès !", "success");
|
+ " vers la note " + dest.name + " a été fait avec succès !", "success");
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}).fail(function (err) {
|
}).fail(function (err) {
|
||||||
addMsg("Le transfert de "
|
$.post("/api/note/transaction/transaction/",
|
||||||
+ pretty_money(source.quantity * dest.quantity * 100 * $("#amount").val()) + " de la note " + source.name
|
{
|
||||||
+ " vers la note " + dest.name + " a échoué : " + err.responseText, "danger");
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
|
"quantity": source.quantity * dest.quantity,
|
||||||
|
"amount": 100 * $("#amount").val(),
|
||||||
|
"reason": $("#reason").val(),
|
||||||
|
"valid": false,
|
||||||
|
"invalidity_reason": "Solde insuffisant",
|
||||||
|
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
|
"resourcetype": "Transaction",
|
||||||
|
"source": source.id,
|
||||||
|
"source_alias": source.name,
|
||||||
|
"destination": dest.id,
|
||||||
|
"destination_alias": dest.name
|
||||||
|
}).done(function () {
|
||||||
|
addMsg("Le transfert de "
|
||||||
|
+ pretty_money(source.quantity * dest.quantity * 100 * $("#amount").val()) + " de la note " + source.name
|
||||||
|
+ " vers la note " + dest.name + " a échoué : Solde insuffisant", "danger");
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
}).fail(function (err) {
|
||||||
|
addMsg("Le transfert de "
|
||||||
|
+ pretty_money(source.quantity * dest.quantity * 100 * $("#amount").val()) + " de la note " + source.name
|
||||||
|
+ " vers la note " + dest.name + " a échoué : " + err.responseText, "danger");
|
||||||
|
|
||||||
|
reset();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -157,15 +203,17 @@ $("#transfer").click(function() {
|
|||||||
"polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE,
|
"polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
"resourcetype": "SpecialTransaction",
|
"resourcetype": "SpecialTransaction",
|
||||||
"source": source,
|
"source": source,
|
||||||
|
"source_alias": source.name,
|
||||||
"destination": dest,
|
"destination": dest,
|
||||||
|
"destination_alias": dest.name,
|
||||||
"last_name": $("#last_name").val(),
|
"last_name": $("#last_name").val(),
|
||||||
"first_name": $("#first_name").val(),
|
"first_name": $("#first_name").val(),
|
||||||
"bank": $("#bank").val()
|
"bank": $("#bank").val()
|
||||||
}, function () {
|
}).done(function () {
|
||||||
addMsg("Le crédit/retrait a bien été effectué !", "success");
|
addMsg("Le crédit/retrait a bien été effectué !", "success");
|
||||||
reset();
|
reset();
|
||||||
}).fail(function (err) {
|
}).fail(function (err) {
|
||||||
addMsg("Le crédit/transfert a échoué : " + err.responseText, "danger");
|
addMsg("Le crédit/retrait a échoué : " + err.responseText, "danger");
|
||||||
reset();
|
reset();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<a class="nav-link" href="{% url 'note:consos' %}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
|
<a class="nav-link" href="{% url 'note:consos' %}"><i class="fa fa-coffee"></i> {% trans 'Consumptions' %}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if "note.transaction"|not_empty_model_list %}
|
||||||
<li class="nav-item active">
|
<li class="nav-item active">
|
||||||
<a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
|
<a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% if "member.club"|not_empty_model_list %}
|
{% if "member.club"|not_empty_model_list %}
|
||||||
<li class="nav-item active">
|
<li class="nav-item active">
|
||||||
<a class="nav-link" href="{% url 'member:club_list' %}"><i class="fa fa-users"></i> {% trans 'Clubs' %}</a>
|
<a class="nav-link" href="{% url 'member:club_list' %}"><i class="fa fa-users"></i> {% trans 'Clubs' %}</a>
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "member/noteowner_detail.html" %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% block content %}
|
|
||||||
|
{% block profile_info %}
|
||||||
|
{% include "member/club_info.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block profile_content %}
|
||||||
|
|
||||||
<form method="post" action="">
|
<form method="post" action="">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@ -10,9 +14,9 @@
|
|||||||
<input type="submit" name="submit" value="Add Members" class="btn btn-primary" id="submit-save">
|
<input type="submit" name="submit" value="Add Members" class="btn btn-primary" id="submit-save">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<!-- Include formset plugin - including jQuery dependency -->
|
{% block extrajavascript %}
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
|
||||||
<script src="{% static 'js/dynamic-formset.js' %}"></script>
|
<script src="{% static 'js/dynamic-formset.js' %}"></script>
|
||||||
<script>
|
<script>
|
||||||
$('.formset-row').formset({
|
$('.formset-row').formset({
|
||||||
|
12
templates/member/alias_update.html
Normal file
12
templates/member/alias_update.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% load django_tables2 crispy_forms_tags i18n %}
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<input id="alias_input" type="text" value=""/>
|
||||||
|
<button id="alias_submit" class="btn btn-primary mx-2" onclick="create_alias( {{ object.note.pk }} )" type="submit">
|
||||||
|
{% trans "Add alias" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="card bg-light shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
{% render_table aliases %}
|
||||||
|
</div>
|
||||||
|
</div>
|
10
templates/member/club_alias.html
Normal file
10
templates/member/club_alias.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "member/club_detail.html" %}
|
||||||
|
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block profile_content %}
|
||||||
|
{% include "member/alias_update.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extrajavascript %}
|
||||||
|
<script src="/static/js/alias.js"></script>
|
||||||
|
{% endblock%}
|
@ -1,5 +1,8 @@
|
|||||||
{% load i18n static pretty_money %}
|
{% load i18n static pretty_money %}
|
||||||
<div class="card bg-light shadow">
|
<div class="card bg-light shadow">
|
||||||
|
<div class="card-header text-center">
|
||||||
|
<h4> Club {{ club.name }} </h4>
|
||||||
|
</div>
|
||||||
<div class="card-top text-center">
|
<div class="card-top text-center">
|
||||||
<a href="{% url 'member:club_update_pic' club.pk %}">
|
<a href="{% url 'member:club_update_pic' club.pk %}">
|
||||||
<img src="{{ club.note.display_image.url }}" class="img-thumbnail mt-2" >
|
<img src="{{ club.note.display_image.url }}" class="img-thumbnail mt-2" >
|
||||||
@ -10,6 +13,9 @@
|
|||||||
<dt class="col-xl-6">{% trans 'name'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'name'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.name}}</dd>
|
<dd class="col-xl-6">{{ club.name}}</dd>
|
||||||
|
|
||||||
|
<dt class="col-xl-6"><a href="{% url 'member:club_detail' club.parent_club.pk %}">{% trans 'Club Parent'|capfirst %}</a></dt>
|
||||||
|
<dd class="col-xl-6"> {{ club.parent_club.name}}</dd>
|
||||||
|
|
||||||
<dt class="col-xl-6">{% trans 'membership start'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'membership start'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.membership_start }}</dd>
|
<dd class="col-xl-6">{{ club.membership_start }}</dd>
|
||||||
|
|
||||||
@ -22,11 +28,19 @@
|
|||||||
<dt class="col-xl-6">{% trans 'membership fee'|capfirst %}</dt>
|
<dt class="col-xl-6">{% trans 'membership fee'|capfirst %}</dt>
|
||||||
<dd class="col-xl-6">{{ club.membership_fee|pretty_money }}</dd>
|
<dd class="col-xl-6">{{ club.membership_fee|pretty_money }}</dd>
|
||||||
|
|
||||||
<dt class="col-xl-6"><a href="{% url 'member:user_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt>
|
<dt class="col-xl-6"><a href="{% url 'member:club_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt>
|
||||||
<dd class="col-xl-6 text-truncate">{{ object.note.alias_set.all|join:", " }}</dd>
|
<dd class="col-xl-6 text-truncate">{{ object.note.alias_set.all|join:", " }}</dd>
|
||||||
|
|
||||||
<dt class="col-xl-3">{% trans 'email'|capfirst %}</dt>
|
<dt class="col-xl-3">{% trans 'email'|capfirst %}</dt>
|
||||||
<dd class="col-xl-9"><a href="mailto:{{ club.email }}">{{ club.email}}</a></dd>
|
<dd class="col-xl-9"><a href="mailto:{{ club.email }}">{{ club.email}}</a></dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-footer text-center">
|
||||||
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_add_member' pk=club.pk %}"> {% trans "Add member" %}</a>
|
||||||
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_update' pk=club.pk %}"> {% trans "Edit" %}</a>
|
||||||
|
<a class="btn btn-primary btn-sm my-1" href="{% url 'member:club_add_member' pk=club.pk %}"> {% trans "Add roles" %}</a>
|
||||||
|
{% url 'member:club_detail' club.pk as club_detail_url %}
|
||||||
|
{%if request.get_full_path != club_detail_url %}
|
||||||
|
<a class="btn btn-primary btn-sm my-1" href="{{ user_profile_url }}">{% trans 'View Profile' %}</a>
|
||||||
|
{% endif %} </div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
{% extends "member/club_detail.html" %}
|
{% extends "member/club_detail.html" %}
|
||||||
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
||||||
|
|
||||||
{% block profile_info %}
|
|
||||||
{% include "member/club_info.html" %}
|
|
||||||
{% endblock%}
|
|
||||||
|
|
||||||
{% block profile_content%}
|
{% block profile_content%}
|
||||||
{% include "member/picture_update.html" %}
|
{% include "member/picture_update.html" %}
|
||||||
{% endblock%}
|
{% endblock%}
|
||||||
|
@ -2,18 +2,9 @@
|
|||||||
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
||||||
|
|
||||||
{% block profile_content %}
|
{% block profile_content %}
|
||||||
<div class="d-flex justify-content-center">
|
{% include "member/alias_update.html"%}
|
||||||
<form class=" text-center form my-2" action="" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form |crispy }}
|
|
||||||
<button class="btn btn-primary mx-2" type="submit">
|
|
||||||
{% trans "Add alias" %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="card bg-light shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
{% render_table aliases %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extrajavascript %}
|
||||||
|
<script src="/static/js/alias.js"></script>
|
||||||
|
{% endblock%}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{% load i18n static pretty_money %}
|
{% load i18n static pretty_money %}
|
||||||
|
|
||||||
<div class="card bg-light shadow">
|
<div class="card bg-light shadow">
|
||||||
|
<div class="card-header text-center" >
|
||||||
|
<h4> {% trans "Account #" %} {{ object.pk }}</h4>
|
||||||
|
</div>
|
||||||
<div class="card-top text-center">
|
<div class="card-top text-center">
|
||||||
<a href="{% url 'member:user_update_pic' object.pk %}">
|
<a href="{% url 'member:user_update_pic' object.pk %}">
|
||||||
<img src="{{ object.note.display_image.url }}" class="img-thumbnail mt-2" >
|
<img src="{{ object.note.display_image.url }}" class="img-thumbnail mt-2" >
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
{% extends "member/noteowner_detail.html" %}
|
{% extends "member/profile_detail.html" %}
|
||||||
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
{% load i18n static pretty_money django_tables2 crispy_forms_tags %}
|
||||||
|
|
||||||
{% block profile_info %}
|
|
||||||
{% include "member/profile_info.html" %}
|
|
||||||
{% endblock%}
|
|
||||||
|
|
||||||
{% block profile_content%}
|
{% block profile_content%}
|
||||||
{% include "member/picture_update.html" %}
|
{% include "member/picture_update.html" %}
|
||||||
{% endblock%}
|
{% endblock%}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</h4>
|
</h4>
|
||||||
<input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved();return(false);" id="search_field"/>
|
<input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved();return(false);" id="search_field"/>
|
||||||
<hr>
|
<hr>
|
||||||
<a class="btn btn-primary text-center my-4" href="{% url 'note:template_create' %}">Créer un bouton</a>
|
<a class="btn btn-primary text-center my-1" href="{% url 'note:template_create' %}">{% trans "New button" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
|
Loading…
Reference in New Issue
Block a user