1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-06-20 17:41:55 +02:00

Add "search transactions page"

This commit is contained in:
Yohann D'ANELLO
2020-08-03 18:49:15 +02:00
parent 55580bc11e
commit 985a5ca876
15 changed files with 455 additions and 196 deletions

View File

@ -3,10 +3,11 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.forms import CheckboxSelectMultiple
from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import Autocomplete, AmountInput
from note_kfet.inputs import Autocomplete, AmountInput, DateTimePickerInput
from .models import TransactionTemplate, NoteClub
from .models import TransactionTemplate, NoteClub, Alias
class ImageForm(forms.Form):
@ -38,3 +39,80 @@ class TransactionTemplateForm(forms.ModelForm):
),
'amount': AmountInput(),
}
class SearchTransactionForm(forms.Form):
source = forms.ModelChoiceField(
queryset=Alias.objects.all(),
label=_("Source"),
required=False,
widget=Autocomplete(
Alias,
resetable=True,
attrs={
'api_url': '/api/note/alias/',
'placeholder': 'Note ...',
},
),
)
destination = forms.ModelChoiceField(
queryset=Alias.objects.all(),
label=_("Destination"),
required=False,
widget=Autocomplete(
Alias,
resetable=True,
attrs={
'api_url': '/api/note/alias/',
'placeholder': 'Note ...',
},
),
)
type = forms.ModelMultipleChoiceField(
queryset=ContentType.objects.filter(app_label="note", model__endswith="transaction"),
initial=ContentType.objects.filter(app_label="note", model__endswith="transaction"),
label=_("Type"),
required=False,
widget=CheckboxSelectMultiple(),
)
reason = forms.CharField(
label=_("Reason"),
required=False,
)
valid = forms.BooleanField(
label=_("Valid"),
initial=False,
required=False,
)
amount_gte = forms.Field(
label=_("Total amount greater than"),
initial=0,
required=False,
widget=AmountInput(),
)
amount_lte = forms.Field(
initial=2 ** 31 - 1,
label=_("Total amount less than"),
required=False,
widget=AmountInput(),
)
created_after = forms.Field(
label=_("Created after"),
initial="2000-01-01 00:00",
required=False,
widget=DateTimePickerInput(),
)
created_before = forms.Field(
label=_("Created before"),
initial="2042-12-31 21:42",
required=False,
widget=DateTimePickerInput(),
)

View File

@ -243,6 +243,7 @@ class RecurrentTransaction(Transaction):
TransactionTemplate,
on_delete=models.PROTECT,
)
category = models.ForeignKey(
TemplateCategory,
on_delete=models.PROTECT,
@ -252,6 +253,10 @@ class RecurrentTransaction(Transaction):
def type(self):
return _('Template')
class Meta:
verbose_name = _("recurrent transaction")
verbose_name_plural = _("recurrent transactions")
class SpecialTransaction(Transaction):
"""
@ -290,6 +295,10 @@ class SpecialTransaction(Transaction):
raise(ValidationError(_("A special transaction is only possible between a"
" Note associated to a payment method and a User or a Club")))
class Meta:
verbose_name = _("Special transaction")
verbose_name_plural = _("Special transactions")
class MembershipTransaction(Transaction):
"""

View File

@ -12,4 +12,5 @@ urlpatterns = [
path('buttons/update/<int:pk>/', views.TransactionTemplateUpdateView.as_view(), name='template_update'),
path('buttons/', views.TransactionTemplateListView.as_view(), name='template_list'),
path('consos/', views.ConsoView.as_view(), name='consos'),
path('transactions/<int:pk>/', views.TransactionSearchView.as_view(), name='transactions'),
]

View File

@ -5,9 +5,9 @@ import json
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.db.models import Q, F
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView
from django.views.generic import CreateView, UpdateView, DetailView
from django_tables2 import SingleTableView
from django.urls import reverse_lazy
@ -16,8 +16,8 @@ from note_kfet.inputs import AmountInput
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin
from .forms import TransactionTemplateForm
from .models import TemplateCategory, Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial
from .forms import TransactionTemplateForm, SearchTransactionForm
from .models import TemplateCategory, Transaction, TransactionTemplate, RecurrentTransaction, NoteSpecial, Note
from .models.transactions import SpecialTransaction
from .tables import HistoryTable, ButtonTable
@ -171,3 +171,51 @@ class ConsoView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
context['no_cache'] = True
return context
class TransactionSearchView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
model = Note
context_object_name = "note"
template_name = "note/search_transactions.html"
extra_context = {"title": _("Search transactions")}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = SearchTransactionForm(data=self.request.GET if self.request.GET else None)
context["form"] = form
form.full_clean()
if form.is_valid():
data = form.cleaned_data
else:
data = {}
transactions = Transaction.objects.annotate(total_amount=F("quantity") * F("amount")).filter(
PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\
.filter(Q(source=self.object) | Q(destination=self.object)).order_by('-created_at')
if "source" in data and data["source"]:
transactions = transactions.filter(source_id=data["source"].note_id)
if "destination" in data and data["destination"]:
transactions = transactions.filter(destination_id=data["destination"].note_id)
if "type" in data and data["type"]:
transactions = transactions.filter(polymorphic_ctype__in=data["type"])
if "reason" in data and data["reason"]:
transactions = transactions.filter(reason__iregex=data["reason"])
if "valid" in data and data["valid"]:
transactions = transactions.filter(valid=data["valid"])
if "amount_gte" in data and data["amount_gte"]:
transactions = transactions.filter(total_amount__gte=data["amount_gte"])
if "amount_lte" in data and data["amount_lte"]:
transactions = transactions.filter(total_amount__lte=data["amount_lte"])
if "created_after" in data and data["created_after"]:
transactions = transactions.filter(created_at__gte=data["created_after"])
if "created_before" in data and data["created_before"]:
transactions = transactions.filter(created_at__lte=data["created_before"])
table = HistoryTable(transactions)
table.paginate(per_page=20)
context["table"] = table
return context

View File

@ -130,7 +130,7 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
context["my_registration"] = my_registration
buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request.user, Bus, "view")) \
.filter(wei=self.object).annotate(count=Count("memberships"))
.filter(wei=self.object).annotate(count=Count("memberships")).order_by("name")
bus_table = BusTable(data=buses, prefix="bus-")
context['buses'] = bus_table
@ -589,9 +589,6 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
form_class = WEIRegistrationForm
extra_context = {"title": _("Update WEI Registration")}
def get_queryset(self, **kwargs):
return WEIRegistration.objects
def dispatch(self, request, *args, **kwargs):
wei = self.get_object().wei
today = date.today()