mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 01:48:21 +02:00
Make erdnaxe be happy
This commit is contained in:
@ -47,11 +47,11 @@ class NoteClubAdmin(PolymorphicChildModelAdmin):
|
||||
"""
|
||||
Child for a club note, see NoteAdmin
|
||||
"""
|
||||
inlines = (AliasInlines, )
|
||||
inlines = (AliasInlines,)
|
||||
|
||||
# We can't change club after creation or the balance
|
||||
readonly_fields = ('club', 'balance')
|
||||
search_fields = ('club', )
|
||||
search_fields = ('club',)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
"""
|
||||
@ -71,7 +71,7 @@ class NoteSpecialAdmin(PolymorphicChildModelAdmin):
|
||||
"""
|
||||
Child for a special note, see NoteAdmin
|
||||
"""
|
||||
readonly_fields = ('balance', )
|
||||
readonly_fields = ('balance',)
|
||||
|
||||
|
||||
@admin.register(NoteUser)
|
||||
@ -79,7 +79,7 @@ class NoteUserAdmin(PolymorphicChildModelAdmin):
|
||||
"""
|
||||
Child for an user note, see NoteAdmin
|
||||
"""
|
||||
inlines = (AliasInlines, )
|
||||
inlines = (AliasInlines,)
|
||||
|
||||
# We can't change user after creation or the balance
|
||||
readonly_fields = ('user', 'balance')
|
||||
@ -133,7 +133,7 @@ class TransactionAdmin(PolymorphicParentModelAdmin):
|
||||
Else the amount of money would not be transferred
|
||||
"""
|
||||
if obj: # user is editing an existing object
|
||||
return 'created_at', 'source', 'destination', 'quantity',\
|
||||
return 'created_at', 'source', 'destination', 'quantity', \
|
||||
'amount'
|
||||
return []
|
||||
|
||||
@ -143,9 +143,9 @@ class TransactionTemplateAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin customisation for TransactionTemplate
|
||||
"""
|
||||
list_display = ('name', 'poly_destination', 'amount', 'category', 'display', )
|
||||
list_display = ('name', 'poly_destination', 'amount', 'category', 'display',)
|
||||
list_filter = ('category', 'display')
|
||||
autocomplete_fields = ('destination', )
|
||||
autocomplete_fields = ('destination',)
|
||||
|
||||
def poly_destination(self, obj):
|
||||
"""
|
||||
@ -161,5 +161,5 @@ class TemplateCategoryAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin customisation for TransactionTemplate
|
||||
"""
|
||||
list_display = ('name', )
|
||||
list_filter = ('name', )
|
||||
list_display = ('name',)
|
||||
list_filter = ('name',)
|
||||
|
@ -13,6 +13,7 @@ class NoteSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Notes.
|
||||
The djangorestframework plugin will analyse the model `Note` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Note
|
||||
fields = '__all__'
|
||||
@ -29,6 +30,7 @@ class NoteClubSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Club's notes.
|
||||
The djangorestframework plugin will analyse the model `NoteClub` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = NoteClub
|
||||
fields = '__all__'
|
||||
@ -39,6 +41,7 @@ class NoteSpecialSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for special notes.
|
||||
The djangorestframework plugin will analyse the model `NoteSpecial` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = NoteSpecial
|
||||
fields = '__all__'
|
||||
@ -49,6 +52,7 @@ class NoteUserSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for User's notes.
|
||||
The djangorestframework plugin will analyse the model `NoteUser` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = NoteUser
|
||||
fields = '__all__'
|
||||
@ -59,6 +63,7 @@ class AliasSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Aliases.
|
||||
The djangorestframework plugin will analyse the model `Alias` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Alias
|
||||
fields = '__all__'
|
||||
@ -78,6 +83,7 @@ class TransactionTemplateSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Transaction templates.
|
||||
The djangorestframework plugin will analyse the model `TransactionTemplate` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = TransactionTemplate
|
||||
fields = '__all__'
|
||||
@ -88,6 +94,7 @@ class TransactionSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Transactions.
|
||||
The djangorestframework plugin will analyse the model `Transaction` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Transaction
|
||||
fields = '__all__'
|
||||
@ -98,6 +105,7 @@ class MembershipTransactionSerializer(serializers.ModelSerializer):
|
||||
REST API Serializer for Membership transactions.
|
||||
The djangorestframework plugin will analyse the model `MembershipTransaction` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = MembershipTransaction
|
||||
fields = '__all__'
|
||||
|
@ -4,11 +4,11 @@
|
||||
from django.db.models import Q
|
||||
from rest_framework import viewsets
|
||||
|
||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction
|
||||
from .serializers import NoteSerializer, NotePolymorphicSerializer, NoteClubSerializer, NoteSpecialSerializer, \
|
||||
NoteUserSerializer, AliasSerializer, \
|
||||
TransactionTemplateSerializer, TransactionSerializer, MembershipTransactionSerializer
|
||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction
|
||||
|
||||
|
||||
class NoteViewSet(viewsets.ModelViewSet):
|
||||
|
@ -3,31 +3,25 @@
|
||||
|
||||
from dal import autocomplete
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import os
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.bootstrap import Div
|
||||
from crispy_forms.layout import Layout, HTML
|
||||
|
||||
from .models import Alias
|
||||
from .models import Transaction, TransactionTemplate, TemplateTransaction
|
||||
from .models import Note, Alias
|
||||
|
||||
|
||||
class AliasForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Alias
|
||||
fields = ("name",)
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
super().__init__(*args,**kwargs)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["name"].label = False
|
||||
self.fields["name"].widget.attrs={"placeholder":_('New Alias')}
|
||||
|
||||
self.fields["name"].widget.attrs = {"placeholder": _('New Alias')}
|
||||
|
||||
|
||||
class ImageForm(forms.Form):
|
||||
image = forms.ImageField(required = False,
|
||||
image = forms.ImageField(required=False,
|
||||
label=_('select an image'),
|
||||
help_text=_('Maximal size: 2MB'))
|
||||
x = forms.FloatField(widget=forms.HiddenInput())
|
||||
@ -35,7 +29,7 @@ class ImageForm(forms.Form):
|
||||
width = forms.FloatField(widget=forms.HiddenInput())
|
||||
height = forms.FloatField(widget=forms.HiddenInput())
|
||||
|
||||
|
||||
|
||||
class TransactionTemplateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = TransactionTemplate
|
||||
@ -48,13 +42,13 @@ class TransactionTemplateForm(forms.ModelForm):
|
||||
# forward=(forward.Const('TYPE', 'note_type') où TYPE est dans {user, club, special}
|
||||
widgets = {
|
||||
'destination':
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +56,6 @@ class TransactionForm(forms.ModelForm):
|
||||
def save(self, commit=True):
|
||||
super().save(commit)
|
||||
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
If the user has no right to transfer funds, then it will be the source of the transfer by default.
|
||||
@ -70,7 +63,7 @@ class TransactionForm(forms.ModelForm):
|
||||
"""
|
||||
|
||||
cleaned_data = super().clean()
|
||||
if not "source" in cleaned_data: # TODO Replace it with "if %user has no right to transfer funds"
|
||||
if "source" not in cleaned_data: # TODO Replace it with "if %user has no right to transfer funds"
|
||||
cleaned_data["source"] = self.user.note
|
||||
|
||||
if cleaned_data["source"].pk == cleaned_data["destination"].pk:
|
||||
@ -78,7 +71,6 @@ class TransactionForm(forms.ModelForm):
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Transaction
|
||||
fields = (
|
||||
@ -91,21 +83,21 @@ class TransactionForm(forms.ModelForm):
|
||||
# Voir ci-dessus
|
||||
widgets = {
|
||||
'source':
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
'destination':
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@ -122,18 +114,18 @@ class ConsoForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = TemplateTransaction
|
||||
fields = ('source', )
|
||||
fields = ('source',)
|
||||
|
||||
# Le champ d'utilisateur est remplacé par un champ d'auto-complétion.
|
||||
# Quand des lettres sont tapées, une requête est envoyée sur l'API d'auto-complétion
|
||||
# et récupère les aliases de note valides
|
||||
widgets = {
|
||||
'source':
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
autocomplete.ModelSelect2(
|
||||
url='note:note_autocomplete',
|
||||
attrs={
|
||||
'data-placeholder': 'Note ...',
|
||||
'data-minimum-input-length': 1,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
"""
|
||||
Defines each note types
|
||||
"""
|
||||
@ -27,7 +28,7 @@ class Note(PolymorphicModel):
|
||||
help_text=_('in centimes, money credited for this instance'),
|
||||
default=0,
|
||||
)
|
||||
last_negative= models.DateTimeField(
|
||||
last_negative = models.DateTimeField(
|
||||
verbose_name=_('last negative date'),
|
||||
help_text=_('last time the balance was negative'),
|
||||
null=True,
|
||||
@ -98,7 +99,7 @@ class Note(PolymorphicModel):
|
||||
# Alias exists, so check if it is linked to this note
|
||||
if aliases.first().note != self:
|
||||
raise ValidationError(_('This alias is already taken.'),
|
||||
code="same_alias",)
|
||||
code="same_alias", )
|
||||
else:
|
||||
# Alias does not exist yet, so check if it can exist
|
||||
a = Alias(name=str(self))
|
||||
@ -231,12 +232,12 @@ class Alias(models.Model):
|
||||
sim_alias = Alias.objects.get(normalized_name=normalized_name)
|
||||
if self != sim_alias:
|
||||
raise ValidationError(_('An alias with a similar name already exists: {} '.format(sim_alias)),
|
||||
code="same_alias"
|
||||
)
|
||||
code="same_alias"
|
||||
)
|
||||
except Alias.DoesNotExist:
|
||||
pass
|
||||
self.normalized_name = normalized_name
|
||||
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
if self.name == str(self.note):
|
||||
raise ValidationError(_("You can't delete your main alias."),
|
||||
|
@ -2,9 +2,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.urls import reverse
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
from .notes import Note, NoteClub
|
||||
@ -44,7 +44,7 @@ class TransactionTemplate(models.Model):
|
||||
verbose_name=_('name'),
|
||||
max_length=255,
|
||||
unique=True,
|
||||
error_messages={'unique':_("A template with this name already exist")},
|
||||
error_messages={'unique': _("A template with this name already exist")},
|
||||
)
|
||||
destination = models.ForeignKey(
|
||||
NoteClub,
|
||||
@ -63,7 +63,7 @@ class TransactionTemplate(models.Model):
|
||||
max_length=31,
|
||||
)
|
||||
display = models.BooleanField(
|
||||
default = True,
|
||||
default=True,
|
||||
)
|
||||
description = models.CharField(
|
||||
verbose_name=_('description'),
|
||||
@ -75,7 +75,7 @@ class TransactionTemplate(models.Model):
|
||||
verbose_name_plural = _("transaction templates")
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('note:template_update', args=(self.pk, ))
|
||||
return reverse('note:template_update', args=(self.pk,))
|
||||
|
||||
|
||||
class Transaction(PolymorphicModel):
|
||||
@ -168,6 +168,7 @@ class TemplateTransaction(Transaction):
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
|
||||
class MembershipTransaction(Transaction):
|
||||
"""
|
||||
Special type of :model:`note.Transaction` associated to a :model:`member.Membership`.
|
||||
|
@ -4,14 +4,16 @@
|
||||
import django_tables2 as tables
|
||||
from django.db.models import F
|
||||
from django_tables2.utils import A
|
||||
from .models.transactions import Transaction
|
||||
|
||||
from .models.notes import Alias
|
||||
from .models.transactions import Transaction
|
||||
|
||||
|
||||
class HistoryTable(tables.Table):
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class':
|
||||
'table table-condensed table-striped table-hover'
|
||||
'table table-condensed table-striped table-hover'
|
||||
}
|
||||
model = Transaction
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
@ -25,21 +27,22 @@ class HistoryTable(tables.Table):
|
||||
.order_by(('-' if is_descending else '') + 'total')
|
||||
return (queryset, True)
|
||||
|
||||
|
||||
class AliasTable(tables.Table):
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class':
|
||||
'table table condensed table-striped table-hover'
|
||||
'table table condensed table-striped table-hover'
|
||||
}
|
||||
model = Alias
|
||||
fields =('name',)
|
||||
fields = ('name',)
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
|
||||
show_header = False
|
||||
name = tables.Column(attrs={'td':{'class':'text-center'}})
|
||||
name = tables.Column(attrs={'td': {'class': 'text-center'}})
|
||||
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')
|
||||
'td': {'class': 'col-sm-2'},
|
||||
'a': {'class': 'btn btn-danger'}},
|
||||
text='delete', accessor='pk')
|
||||
|
@ -8,8 +8,8 @@ from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, ListView, UpdateView
|
||||
|
||||
from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction
|
||||
from .forms import TransactionForm, TransactionTemplateForm, ConsoForm
|
||||
from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction
|
||||
|
||||
|
||||
class TransactionCreate(LoginRequiredMixin, CreateView):
|
||||
@ -53,6 +53,7 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView):
|
||||
"""
|
||||
Auto complete note by aliases
|
||||
"""
|
||||
|
||||
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.
|
||||
@ -66,7 +67,7 @@ class NoteAutocomplete(autocomplete.Select2QuerySetView):
|
||||
|
||||
# self.q est le paramètre de la recherche
|
||||
if self.q:
|
||||
qs = qs.filter(Q(name__regex=self.q) | Q(normalized_name__regex=Alias.normalize(self.q)))\
|
||||
qs = qs.filter(Q(name__regex=self.q) | Q(normalized_name__regex=Alias.normalize(self.q))) \
|
||||
.order_by('normalized_name').distinct()
|
||||
|
||||
# Filtrage par type de note (user, club, special)
|
||||
@ -147,4 +148,3 @@ class ConsoView(LoginRequiredMixin, CreateView):
|
||||
When clicking a button, reload the same page
|
||||
"""
|
||||
return reverse('note:consos')
|
||||
|
||||
|
Reference in New Issue
Block a user