Refactor transaction URL handling and enhance filter form functionality

Close 
This commit is contained in:
Edgar P. Burkhart 2025-01-04 21:14:46 +01:00
parent 02c53c7dab
commit d44407d9ab
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
9 changed files with 73 additions and 22 deletions
nummi
category/templates/category
main
static/main/js
templatetags
statement/templates/statement
transaction
pkgbuild

View file

@ -15,7 +15,7 @@
</p>
<section>
<h3>{% translate "Transactions" %}</h3>
{% url "category_transactions" category.id as t_url %}
{% url_get "transactions" category=category.id as t_url %}
<p>
<a class="big-link" href="{{ t_url }}">{{ "list-check"|remixnl }}{% translate "View all transactions" %}</a>
</p>

View file

@ -22,9 +22,9 @@
<th scope="row" class="l wi">
{% if cat.category %}
{% if month %}
<a href="{% url "category_transaction_month" cat.category month.year month.month %}">{{ cat.category__icon|remix }}{{ cat.category__name }}</a>
<a href="{% url_get "transactions" category=cat.category start_date=month end_date=month|end_of_month %}">{{ cat.category__icon|remix }}{{ cat.category__name }}</a>
{% elif year %}
<a href="{% url "category_transaction_year" cat.category year.year %}">{{ cat.category__icon|remix }}{{ cat.category__name }}</a>
<a href="{% url_get "transactions" category=cat.category start_date=year end_date=year|end_of_year %}">{{ cat.category__icon|remix }}{{ cat.category__name }}</a>
{% else %}
{{ cat.category__icon|remix }}{{ cat.category__name }}
{% endif %}

View file

@ -153,9 +153,27 @@ if (accounts) {
const filterForm = document.querySelector("form.filter");
if (filterForm) {
const accountSelect = filterForm.querySelector("[name='account']");
const statementSelect = filterForm.querySelector("[name='statement']");
if (!statementSelect.disabled) {
accountSelect.addEventListener("input", (event) => {
statementSelect.value = "";
statementSelect.disabled = true;
});
filterForm.addEventListener("reset", (event) => {
statementSelect.disabled = false;
});
}
let disableStatement = false;
filterForm.addEventListener("submit", (event) => {
for (element of filterForm.elements) {
if (element.value == "") {
if (
element.value == "" ||
(disableStatement && element.name == "statement")
) {
if (element.name == "account") {
disableStatement = true;
}
element.disabled = true;
}
}

View file

@ -1,5 +1,9 @@
from urllib import parse
from dateutil.relativedelta import relativedelta
from django import template
from django.templatetags.static import static
from django.urls import reverse
from django.utils import formats
from django.utils.safestring import mark_safe
@ -118,3 +122,18 @@ def page_url(context, page):
query = context["request"].GET.copy()
query["page"] = page
return query.urlencode()
@register.simple_tag
def url_get(name, **kwargs):
return f"{reverse(name)}?{parse.urlencode(kwargs)}"
@register.filter
def end_of_month(month):
return month + relativedelta(months=1, days=-1)
@register.filter
def end_of_year(year):
return year + relativedelta(years=1, days=-1)

View file

@ -55,7 +55,7 @@
</div>
<section>
<h3>{% translate "Transactions" %}</h3>
{% url "statement_transactions" statement.id as t_url %}
{% url_get "transactions" account=account.id statement=statement.id as t_url %}
<p>
<a class="big-link"
href="{% url "new_transaction" statement=statement.id %}">{{ "add-circle"|remix }}{% translate "Add transaction" %}</a>

View file

@ -172,6 +172,7 @@ class TransactionFiltersForm(forms.Form):
account = forms.ModelChoiceField(
queryset=None, required=False, widget=AccountSelect()
)
statement = forms.ModelChoiceField(queryset=None, required=False)
search = forms.CharField(label=_("Search"), required=False)
sort_by = forms.ChoiceField(
label=_("Sort by"),
@ -191,6 +192,14 @@ class TransactionFiltersForm(forms.Form):
self.fields["category"].queryset = _user.category_set
self.fields["account"].queryset = _user.account_set
print(kwargs.get("initial"))
if acc_id := kwargs.get("initial", {}).get("account"):
self.fields["statement"].queryset = (
self.fields["account"].queryset.get(id=acc_id).statement_set
)
else:
self.fields["statement"].queryset = _user.statement_set.none()
self.fields["statement"].disabled = True
self.fields["category"].widget.attrs |= {
"class": "category",

View file

@ -1,19 +1,21 @@
{% load i18n %}
<details {% if filters %}open{% endif %}>
<summary>{% translate "Filters" %}</summary>
<form class="filter" method="get">
{% for field in form %}
<div class="field">
<label>{{ field.label }}</label>
{{ field }}
{% if form %}
<details {% if filters %}open{% endif %}>
<summary>{% translate "Filters" %}</summary>
<form class="filter" method="get">
{% for field in form %}
<div class="field">
<label>{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<div class="buttons">
<input type="submit" value="{% translate "Filter" %}">
<input type="reset" value="{% translate "Reset" %}">
{% if filters %}
<a href="?" class="del">{% translate "Clear" %}</a>
{% endif %}
</div>
{% endfor %}
<div class="buttons">
<input type="submit" value="{% translate "Filter" %}">
<input type="reset" value="{% translate "Reset" %}">
{% if filters %}
<a href="?" class="del">{% translate "Clear" %}</a>
{% endif %}
</div>
</form>
</details>
</form>
</details>
{% endif %}

View file

@ -190,6 +190,8 @@ class TransactionListView(NummiListView):
queryset = queryset.filter(category=category)
if account := self.request.GET.get("account"):
queryset = queryset.filter(statement__account=account)
if statement := self.request.GET.get("statement"):
queryset = queryset.filter(statement=statement)
if search := self.request.GET.get("search"):
queryset = (
queryset.annotate(

View file

@ -10,6 +10,7 @@ depends=(
"python-django"
"python-toml"
"python-psycopg"
"python-dateutil"
)
makedepends=("git")
optdepends=("postgresql: database")