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:
@ -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(),
|
||||
)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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'),
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user